diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ac7297f8f1b..93a632b53b24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5668,6 +5668,7 @@ Released 2018-09-13 [`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations [`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap [`unnecessary_map_on_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_on_constructor +[`unnecessary_min`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_min [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation [`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index f88ab9fe440f..5efa97a0b8e8 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -645,8 +645,7 @@ impl Conf { } }, Err(error) => { - sess.dcx() - .err(format!("error finding Clippy's configuration file: {error}")); + sess.dcx().err(format!("error finding Clippy's configuration file: {error}")); }, } diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index 471ad73e2074..6307d46a53df 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -107,8 +107,7 @@ impl Msrv { if let Some(msrv_attr) = msrv_attrs.next() { if let Some(duplicate) = msrv_attrs.last() { - sess.dcx() - .struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times") + sess.dcx().struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times") .span_note(msrv_attr.span, "first definition found here") .emit(); } @@ -118,8 +117,7 @@ impl Msrv { return Some(version); } - sess.dcx() - .span_err(msrv_attr.span, format!("`{msrv}` is not a valid Rust 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"); } diff --git a/clippy_lints/src/async_yields_async.rs b/clippy_lints/src/async_yields_async.rs index bb08ac7508bc..677193995b65 100644 --- a/clippy_lints/src/async_yields_async.rs +++ b/clippy_lints/src/async_yields_async.rs @@ -2,7 +2,10 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; -use rustc_hir::{Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, QPath}; +use rustc_hir::{ + Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, QPath, +}; + use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 9dd22135d95c..8c60693c7782 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -447,6 +447,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::UNNECESSARY_JOIN_INFO, crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO, crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO, + crate::methods::UNNECESSARY_MIN_INFO, crate::methods::UNNECESSARY_SORT_BY_INFO, crate::methods::UNNECESSARY_TO_OWNED_INFO, crate::methods::UNWRAP_OR_DEFAULT_INFO, diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index c09d3d1862b0..8c032b170236 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -8,8 +8,8 @@ use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::{ AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, - ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath, - TraitItemRef, TyKind, TypeBindingKind, + ImplicitSelfKind, Item, ItemKind, Mutability, Node, PatKind, PathSegment, PrimTy, QPath, TraitItemRef, + TyKind, TypeBindingKind, OpaqueTyOrigin, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index 4cd5f3b81e52..c3d5bb64373b 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -3,9 +3,9 @@ use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl, - FnRetTy, GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, - TypeBindingKind, + Block, Body, Closure, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl, FnRetTy, + GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, + TypeBindingKind, ClosureKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -171,14 +171,23 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) .iter() .all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt)) } - -fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { +fn desugared_async_block<'tcx>( + cx: &LateContext<'tcx>, + block: &'tcx Block<'tcx>, +) -> Option<&'tcx Body<'tcx>> { if let Some(Expr { - kind: ExprKind::Closure(&Closure { kind, body, .. }), + kind: + ExprKind::Closure(&Closure { + kind: + ClosureKind::Coroutine(CoroutineKind::Desugared( + CoroutineDesugaring::Async, + CoroutineSource::Block, + )), + body, + .. + }), .. }) = block.expr - && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block)) = - kind { return Some(cx.tcx.hir().body(body)); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 25b1ea526e2e..3e0cfd8fe4e8 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -110,6 +110,7 @@ mod unnecessary_iter_cloned; mod unnecessary_join; mod unnecessary_lazy_eval; mod unnecessary_literal_unwrap; +mod unnecessary_min; mod unnecessary_sort_by; mod unnecessary_to_owned; mod unwrap_expect_used; @@ -3754,6 +3755,27 @@ declare_clippy_lint! { "using `Option.map_or(Err(_), Ok)`, which is more succinctly expressed as `Option.ok_or(_)`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for unnecessary calls to `min()` + /// + /// ### Why is this bad? + /// + /// In these cases it is not necessary to call `min()` + /// ### Example + /// ```no_run + /// let _ = 0.min(7_u32); + /// ``` + /// Use instead: + /// ```no_run + /// let _ = 7; + /// ``` + #[clippy::version = "1.76.0"] + pub UNNECESSARY_MIN, + complexity, + "using 'min()' when there is no need for it" +} + declare_clippy_lint! { /// ### What it does /// Checks for iterators of `Result`s using `.filter(Result::is_ok).map(Result::unwrap)` that may @@ -3980,6 +4002,7 @@ impl_lint_pass!(Methods => [ UNNECESSARY_FALLIBLE_CONVERSIONS, JOIN_ABSOLUTE_PATHS, OPTION_MAP_OR_ERR_OK, + UNNECESSARY_MIN, RESULT_FILTER_MAP, ITER_FILTER_IS_SOME, ITER_FILTER_IS_OK, @@ -4264,6 +4287,7 @@ impl Methods { Some(("bytes", recv2, [], _, _)) => bytes_count_to_len::check(cx, expr, recv, recv2), _ => {}, }, + ("min", [arg]) => unnecessary_min::check(cx, expr, recv, arg), ("drain", ..) => { if let Node::Stmt(Stmt { hir_id: _, kind, .. }) = cx.tcx.hir().get_parent(expr.hir_id) && matches!(kind, StmtKind::Semi(_)) diff --git a/clippy_lints/src/methods/unnecessary_min.rs b/clippy_lints/src/methods/unnecessary_min.rs new file mode 100644 index 000000000000..5a9593e7d592 --- /dev/null +++ b/clippy_lints/src/methods/unnecessary_min.rs @@ -0,0 +1,111 @@ +use std::cmp::Ordering; + +use super::UNNECESSARY_MIN; +use clippy_utils::diagnostics::span_lint_and_sugg; + +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::source::snippet; +use clippy_utils::{clip, int_bits, unsext}; +use hir::Expr; + +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use rustc_middle::ty; +use rustc_span::Span; + +pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) { + if both_are_constant(cx, expr, recv, arg) { + return; + } + one_extrema(cx, expr, recv, arg); +} +fn lint(cx: &LateContext<'_>, expr: &Expr<'_>, sugg: Span, other: Span) { + let msg = format!( + "`{}` is never greater than `{}` and has therefore no effect", + snippet(cx, sugg, "Not yet implemented"), + snippet(cx, other, "Not yet implemented") + ); + span_lint_and_sugg( + cx, + UNNECESSARY_MIN, + expr.span, + &msg, + "try", + snippet(cx, sugg, "Not yet implemented").to_string(), + Applicability::MachineApplicable, + ); +} + +fn try_to_eval<'tcx>( + cx: &LateContext<'tcx>, + recv: &'tcx Expr<'_>, + arg: &'tcx Expr<'_>, +) -> (Option>, Option>) { + ( + (constant(cx, cx.typeck_results(), recv)), + (constant(cx, cx.typeck_results(), arg)), + ) +} +#[derive(Debug)] +enum Extrema { + Minimum, + Maximum, +} +fn detect_extrema<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option { + let ty = cx.typeck_results().expr_ty(expr); + + let cv = constant(cx, cx.typeck_results(), expr)?; + + match (ty.kind(), cv) { + (&ty::Uint(_), Constant::Int(0)) => Some(Extrema::Minimum), + (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) => { + Some(Extrema::Minimum) + }, + + (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) => { + Some(Extrema::Maximum) + }, + (&ty::Uint(uty), Constant::Int(i)) if i == clip(cx.tcx, u128::MAX, uty) => Some(Extrema::Maximum), + + _ => None, + } +} +fn both_are_constant<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + recv: &'tcx Expr<'_>, + arg: &'tcx Expr<'_>, +) -> bool { + let ty = cx.typeck_results().expr_ty(recv); + if let (Some(left), Some(right)) = try_to_eval(cx, recv, arg) + && let Some(ord) = Constant::partial_cmp(cx.tcx, ty, &left, &right) + { + let (sugg, other) = match ord { + Ordering::Less => (recv.span, arg.span), + Ordering::Equal | Ordering::Greater => (arg.span, recv.span), + }; + + lint(cx, expr, sugg, other); + return true; + } + false +} +fn one_extrema<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) -> bool { + if let Some(extrema) = detect_extrema(cx, recv) { + match extrema { + Extrema::Minimum => lint(cx, expr, recv.span, arg.span), + Extrema::Maximum => lint(cx, expr, arg.span, recv.span), + } + return true; + } else if let Some(extrema) = detect_extrema(cx, arg) { + match extrema { + Extrema::Minimum => lint(cx, expr, arg.span, recv.span), + Extrema::Maximum => lint(cx, expr, recv.span, arg.span), + } + return true; + } + + false +} diff --git a/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs index 0ed957f1f2fb..417b4db38062 100644 --- a/clippy_lints/src/redundant_async_block.rs +++ b/clippy_lints/src/redundant_async_block.rs @@ -6,9 +6,7 @@ use clippy_utils::source::{snippet, walk_span_to_context}; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::for_each_expr; use rustc_errors::Applicability; -use rustc_hir::{ - Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSource, -}; +use rustc_hir::{Closure, ClosureKind, CoroutineKind, CoroutineSource, CoroutineDesugaring, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::UpvarCapture; @@ -77,13 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if let ExprKind::Closure(Closure { body, def_id, kind, .. }) = expr.kind && let body = cx.tcx.hir().body(*body) - && matches!( - kind, - ClosureKind::Coroutine(CoroutineKind::Desugared( - CoroutineDesugaring::Async, - CoroutineSource::Block - )) - ) + && matches!(kind, ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block))) { cx.typeck_results() .closure_min_captures diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index cde08dfcc748..16c929edb928 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -5,7 +5,7 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; -use rustc_hir::{intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Node}; +use rustc_hir::{intravisit as hir_visit, CoroutineKind, CoroutineSource, CoroutineDesugaring, Node, ClosureKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; @@ -66,8 +66,7 @@ impl<'tcx> Visitor<'tcx> for ReturnVisitor { fn is_async_closure(body: &hir::Body<'_>) -> bool { if let hir::ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind // checks whether it is `async || whatever_expression` - && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) - = innermost_closure_generated_by_desugar.kind + && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) = innermost_closure_generated_by_desugar.kind { true } else { diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index db80e07ca1c4..46c96fad884f 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -76,14 +76,12 @@ pub fn get_attr<'a>( }) .map_or_else( || { - sess.dcx() - .span_err(attr_segments[1].ident.span, "usage of unknown attribute"); + sess.dcx().span_err(attr_segments[1].ident.span, "usage of unknown attribute"); false }, |deprecation_status| { - let mut diag = sess - .dcx() - .struct_span_err(attr_segments[1].ident.span, "usage of deprecated attribute"); + let mut diag = + sess.dcx().struct_span_err(attr_segments[1].ident.span, "usage of deprecated attribute"); match *deprecation_status { DeprecationStatus::Deprecated => { diag.emit(); @@ -134,8 +132,7 @@ pub fn get_unique_attr<'a>( let mut unique_attr: Option<&ast::Attribute> = None; for attr in get_attr(sess, attrs, name) { if let Some(duplicate) = unique_attr { - sess.dcx() - .struct_span_err(attr.span, format!("`{name}` is defined multiple times")) + sess.dcx().struct_span_err(attr.span, format!("`{name}` is defined multiple times")) .span_note(duplicate.span, "first definition found here") .emit(); } else { diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 1ca18170f8a0..439cb02a38f6 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -8,7 +8,12 @@ clippy::cast_sign_loss, clippy::cast_possible_wrap )] -#![allow(clippy::cast_abs_to_unsigned, clippy::no_effect, clippy::unnecessary_operation)] +#![allow( + clippy::cast_abs_to_unsigned, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::unnecessary_min +)] fn main() { // Test clippy::cast_precision_loss diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index bc74f7b728e8..6e916b446011 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -1,5 +1,5 @@ error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> $DIR/cast.rs:16:5 + --> $DIR/cast.rs:21:5 | LL | x0 as f32; | ^^^^^^^^^ @@ -8,37 +8,37 @@ LL | x0 as f32; = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]` error: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> $DIR/cast.rs:20:5 + --> $DIR/cast.rs:25:5 | 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) - --> $DIR/cast.rs:22:5 + --> $DIR/cast.rs:27: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) - --> $DIR/cast.rs:25:5 + --> $DIR/cast.rs:30: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) - --> $DIR/cast.rs:28:5 + --> $DIR/cast.rs:33: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) - --> $DIR/cast.rs:30:5 + --> $DIR/cast.rs:35:5 | LL | x3 as f64; | ^^^^^^^^^ error: casting `f32` to `i32` may truncate the value - --> $DIR/cast.rs:33:5 + --> $DIR/cast.rs:38: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 - --> $DIR/cast.rs:35:5 + --> $DIR/cast.rs:40: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 - --> $DIR/cast.rs:35:5 + --> $DIR/cast.rs:40: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 - --> $DIR/cast.rs:39:5 + --> $DIR/cast.rs:44: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 - --> $DIR/cast.rs:41:5 + --> $DIR/cast.rs:46:5 | LL | 1i32 as i8; | ^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | i8::try_from(1i32); | ~~~~~~~~~~~~~~~~~~ error: casting `i32` to `u8` may truncate the value - --> $DIR/cast.rs:43:5 + --> $DIR/cast.rs:48:5 | LL | 1i32 as u8; | ^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | u8::try_from(1i32); | ~~~~~~~~~~~~~~~~~~ error: casting `f64` to `isize` may truncate the value - --> $DIR/cast.rs:45:5 + --> $DIR/cast.rs:50:5 | LL | 1f64 as isize; | ^^^^^^^^^^^^^ @@ -105,7 +105,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 - --> $DIR/cast.rs:47:5 + --> $DIR/cast.rs:52:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ @@ -113,13 +113,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 - --> $DIR/cast.rs:47:5 + --> $DIR/cast.rs:52:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting `u32` to `u16` may truncate the value - --> $DIR/cast.rs:50:5 + --> $DIR/cast.rs:55:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | u16::try_from(1f32 as u32); | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `f32` to `u32` may truncate the value - --> $DIR/cast.rs:50:5 + --> $DIR/cast.rs:55:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ @@ -139,13 +139,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 - --> $DIR/cast.rs:50:5 + --> $DIR/cast.rs:55:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ error: casting `i32` to `i8` may truncate the value - --> $DIR/cast.rs:55:22 + --> $DIR/cast.rs:60:22 | LL | let _x: i8 = 1i32 as _; | ^^^^^^^^^ @@ -157,7 +157,7 @@ LL | let _x: i8 = 1i32.try_into(); | ~~~~~~~~~~~~~~~ error: casting `f32` to `i32` may truncate the value - --> $DIR/cast.rs:57:9 + --> $DIR/cast.rs:62:9 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -165,7 +165,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 - --> $DIR/cast.rs:59:9 + --> $DIR/cast.rs:64:9 | LL | 1f64 as i32; | ^^^^^^^^^^^ @@ -173,7 +173,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 - --> $DIR/cast.rs:61:9 + --> $DIR/cast.rs:66:9 | LL | 1f32 as u8; | ^^^^^^^^^^ @@ -181,13 +181,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 - --> $DIR/cast.rs:61:9 + --> $DIR/cast.rs:66:9 | LL | 1f32 as u8; | ^^^^^^^^^^ error: casting `u8` to `i8` may wrap around the value - --> $DIR/cast.rs:66:5 + --> $DIR/cast.rs:71:5 | LL | 1u8 as i8; | ^^^^^^^^^ @@ -196,31 +196,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 - --> $DIR/cast.rs:69:5 + --> $DIR/cast.rs:74:5 | LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting `u32` to `i32` may wrap around the value - --> $DIR/cast.rs:71:5 + --> $DIR/cast.rs:76:5 | LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting `u64` to `i64` may wrap around the value - --> $DIR/cast.rs:73:5 + --> $DIR/cast.rs:78:5 | LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting `usize` to `isize` may wrap around the value - --> $DIR/cast.rs:75:5 + --> $DIR/cast.rs:80:5 | LL | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting `usize` to `i8` may truncate the value - --> $DIR/cast.rs:78:5 + --> $DIR/cast.rs:83:5 | LL | 1usize as i8; | ^^^^^^^^^^^^ @@ -232,7 +232,7 @@ LL | i8::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i16` may truncate the value - --> $DIR/cast.rs:81:5 + --> $DIR/cast.rs:86:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -244,7 +244,7 @@ LL | i16::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers - --> $DIR/cast.rs:81:5 + --> $DIR/cast.rs:86:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -253,7 +253,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 - --> $DIR/cast.rs:86:5 + --> $DIR/cast.rs:91:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -265,19 +265,19 @@ LL | i32::try_from(1usize); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:86:5 + --> $DIR/cast.rs:91:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:90:5 + --> $DIR/cast.rs:95:5 | LL | 1usize as i64; | ^^^^^^^^^^^^^ error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers - --> $DIR/cast.rs:95:5 + --> $DIR/cast.rs:100:5 | LL | 1u16 as isize; | ^^^^^^^^^^^^^ @@ -286,13 +286,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 - --> $DIR/cast.rs:99:5 + --> $DIR/cast.rs:104:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:102:5 + --> $DIR/cast.rs:107:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ @@ -304,25 +304,25 @@ LL | isize::try_from(1u64); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast.rs:102:5 + --> $DIR/cast.rs:107:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> $DIR/cast.rs:107:5 + --> $DIR/cast.rs:112:5 | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> $DIR/cast.rs:110:5 + --> $DIR/cast.rs:115:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting `i64` to `i8` may truncate the value - --> $DIR/cast.rs:179:5 + --> $DIR/cast.rs:184:5 | LL | (-99999999999i64).min(1) as i8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -334,7 +334,7 @@ LL | i8::try_from((-99999999999i64).min(1)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `u8` may truncate the value - --> $DIR/cast.rs:193:5 + --> $DIR/cast.rs:198:5 | LL | 999999u64.clamp(0, 256) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -346,7 +346,7 @@ LL | u8::try_from(999999u64.clamp(0, 256)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E2` to `u8` may truncate the value - --> $DIR/cast.rs:216:21 + --> $DIR/cast.rs:221:21 | LL | let _ = self as u8; | ^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | let _ = u8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E2::B` to `u8` will truncate the value - --> $DIR/cast.rs:218:21 + --> $DIR/cast.rs:223:21 | LL | let _ = Self::B as u8; | ^^^^^^^^^^^^^ @@ -367,7 +367,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 - --> $DIR/cast.rs:260:21 + --> $DIR/cast.rs:265:21 | LL | let _ = self as i8; | ^^^^^^^^^^ @@ -379,13 +379,13 @@ LL | let _ = i8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E5::A` to `i8` will truncate the value - --> $DIR/cast.rs:262:21 + --> $DIR/cast.rs:267:21 | LL | let _ = Self::A as i8; | ^^^^^^^^^^^^^ error: casting `main::E6` to `i16` may truncate the value - --> $DIR/cast.rs:279:21 + --> $DIR/cast.rs:284:21 | LL | let _ = self as i16; | ^^^^^^^^^^^ @@ -397,7 +397,7 @@ LL | let _ = i16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:298:21 + --> $DIR/cast.rs:303:21 | LL | let _ = self as usize; | ^^^^^^^^^^^^^ @@ -409,7 +409,7 @@ LL | let _ = usize::try_from(self); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E10` to `u16` may truncate the value - --> $DIR/cast.rs:345:21 + --> $DIR/cast.rs:350:21 | LL | let _ = self as u16; | ^^^^^^^^^^^ @@ -421,7 +421,7 @@ LL | let _ = u16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> $DIR/cast.rs:356:13 + --> $DIR/cast.rs:361:13 | LL | let c = (q >> 16) as u8; | ^^^^^^^^^^^^^^^ @@ -433,7 +433,7 @@ LL | let c = u8::try_from(q >> 16); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> $DIR/cast.rs:360:13 + --> $DIR/cast.rs:365:13 | LL | let c = (q / 1000) as u8; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_min.fixed b/tests/ui/unnecessary_min.fixed new file mode 100644 index 000000000000..a81f1dabc481 --- /dev/null +++ b/tests/ui/unnecessary_min.fixed @@ -0,0 +1,45 @@ +#![allow(unused)] +#![warn(clippy::unnecessary_min)] + +fn main() { + const A: i64 = 45; + const B: i64 = -1; + const C: i64 = const_fn(B); + let _ = (A * B); // Both are constants + let _ = B; // Both are constants + let _ = B; // Both are constants + + let _ = (-6_i32); // Both are Literals + let _ = 6; // Both are Literals + + let _ = 6; // Both are Literals + + let _ = 0; // unsigned with zero + let _ = 0_u32; // unsigned with zero + + let _ = i32::MIN; // singed MIN + let _ = i32::MIN; // singed MIN + + let _ = 42; // singed MAX + let _ = 42; // singed MAX + + let _ = 0; // unsigned with zero and function + + let _ = 0; // unsigned with zero and function + + let _ = i64::MIN; // signed with MIN and function + + let _ = i64::MIN; // signed with MIN and function + + let _ = test_i64(); // signed with MAX and function + let _ = test_i64(); // signed with MAX and function +} +fn test_usize() -> usize { + 42 +} +fn test_i64() -> i64 { + 42 +} +const fn const_fn(input: i64) -> i64 { + -2 * input +} diff --git a/tests/ui/unnecessary_min.rs b/tests/ui/unnecessary_min.rs new file mode 100644 index 000000000000..8c6e50fd04b7 --- /dev/null +++ b/tests/ui/unnecessary_min.rs @@ -0,0 +1,45 @@ +#![allow(unused)] +#![warn(clippy::unnecessary_min)] + +fn main() { + const A: i64 = 45; + const B: i64 = -1; + const C: i64 = const_fn(B); + let _ = (A * B).min(B); // Both are constants + let _ = C.min(B); // Both are constants + let _ = B.min(C); // Both are constants + + let _ = (-6_i32).min(9); // Both are Literals + let _ = 9_u32.min(6); // Both are Literals + + let _ = 6.min(7_u8); // Both are Literals + + let _ = 0.min(7_u8); // unsigned with zero + let _ = 7.min(0_u32); // unsigned with zero + + let _ = i32::MIN.min(42); // singed MIN + let _ = 42.min(i32::MIN); // singed MIN + + let _ = i32::MAX.min(42); // singed MAX + let _ = 42.min(i32::MAX); // singed MAX + + let _ = 0.min(test_usize()); // unsigned with zero and function + + let _ = test_usize().min(0); // unsigned with zero and function + + let _ = i64::MIN.min(test_i64()); // signed with MIN and function + + let _ = test_i64().min(i64::MIN); // signed with MIN and function + + let _ = i64::MAX.min(test_i64()); // signed with MAX and function + let _ = test_i64().min(i64::MAX); // signed with MAX and function +} +fn test_usize() -> usize { + 42 +} +fn test_i64() -> i64 { + 42 +} +const fn const_fn(input: i64) -> i64 { + -2 * input +} diff --git a/tests/ui/unnecessary_min.stderr b/tests/ui/unnecessary_min.stderr new file mode 100644 index 000000000000..610f34416c25 --- /dev/null +++ b/tests/ui/unnecessary_min.stderr @@ -0,0 +1,113 @@ +error: `(A * B)` is never greater than `B` and has therefore no effect + --> $DIR/unnecessary_min.rs:8:13 + | +LL | let _ = (A * B).min(B); // Both are constants + | ^^^^^^^^^^^^^^ help: try: `(A * B)` + | + = note: `-D clippy::unnecessary-min` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_min)]` + +error: `B` is never greater than `C` and has therefore no effect + --> $DIR/unnecessary_min.rs:9:13 + | +LL | let _ = C.min(B); // Both are constants + | ^^^^^^^^ help: try: `B` + +error: `B` is never greater than `C` and has therefore no effect + --> $DIR/unnecessary_min.rs:10:13 + | +LL | let _ = B.min(C); // Both are constants + | ^^^^^^^^ help: try: `B` + +error: `(-6_i32)` is never greater than `9` and has therefore no effect + --> $DIR/unnecessary_min.rs:12:13 + | +LL | let _ = (-6_i32).min(9); // Both are Literals + | ^^^^^^^^^^^^^^^ help: try: `(-6_i32)` + +error: `6` is never greater than `9_u32` and has therefore no effect + --> $DIR/unnecessary_min.rs:13:13 + | +LL | let _ = 9_u32.min(6); // Both are Literals + | ^^^^^^^^^^^^ help: try: `6` + +error: `6` is never greater than `7_u8` and has therefore no effect + --> $DIR/unnecessary_min.rs:15:13 + | +LL | let _ = 6.min(7_u8); // Both are Literals + | ^^^^^^^^^^^ help: try: `6` + +error: `0` is never greater than `7_u8` and has therefore no effect + --> $DIR/unnecessary_min.rs:17:13 + | +LL | let _ = 0.min(7_u8); // unsigned with zero + | ^^^^^^^^^^^ help: try: `0` + +error: `0_u32` is never greater than `7` and has therefore no effect + --> $DIR/unnecessary_min.rs:18:13 + | +LL | let _ = 7.min(0_u32); // unsigned with zero + | ^^^^^^^^^^^^ help: try: `0_u32` + +error: `i32::MIN` is never greater than `42` and has therefore no effect + --> $DIR/unnecessary_min.rs:20:13 + | +LL | let _ = i32::MIN.min(42); // singed MIN + | ^^^^^^^^^^^^^^^^ help: try: `i32::MIN` + +error: `i32::MIN` is never greater than `42` and has therefore no effect + --> $DIR/unnecessary_min.rs:21:13 + | +LL | let _ = 42.min(i32::MIN); // singed MIN + | ^^^^^^^^^^^^^^^^ help: try: `i32::MIN` + +error: `42` is never greater than `i32::MAX` and has therefore no effect + --> $DIR/unnecessary_min.rs:23:13 + | +LL | let _ = i32::MAX.min(42); // singed MAX + | ^^^^^^^^^^^^^^^^ help: try: `42` + +error: `42` is never greater than `i32::MAX` and has therefore no effect + --> $DIR/unnecessary_min.rs:24:13 + | +LL | let _ = 42.min(i32::MAX); // singed MAX + | ^^^^^^^^^^^^^^^^ help: try: `42` + +error: `0` is never greater than `test_usize()` and has therefore no effect + --> $DIR/unnecessary_min.rs:26:13 + | +LL | let _ = 0.min(test_usize()); // unsigned with zero and function + | ^^^^^^^^^^^^^^^^^^^ help: try: `0` + +error: `0` is never greater than `test_usize()` and has therefore no effect + --> $DIR/unnecessary_min.rs:28:13 + | +LL | let _ = test_usize().min(0); // unsigned with zero and function + | ^^^^^^^^^^^^^^^^^^^ help: try: `0` + +error: `i64::MIN` is never greater than `test_i64()` and has therefore no effect + --> $DIR/unnecessary_min.rs:30:13 + | +LL | let _ = i64::MIN.min(test_i64()); // signed with MIN and function + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i64::MIN` + +error: `i64::MIN` is never greater than `test_i64()` and has therefore no effect + --> $DIR/unnecessary_min.rs:32:13 + | +LL | let _ = test_i64().min(i64::MIN); // signed with MIN and function + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i64::MIN` + +error: `test_i64()` is never greater than `i64::MAX` and has therefore no effect + --> $DIR/unnecessary_min.rs:34:13 + | +LL | let _ = i64::MAX.min(test_i64()); // signed with MAX and function + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `test_i64()` + +error: `test_i64()` is never greater than `i64::MAX` and has therefore no effect + --> $DIR/unnecessary_min.rs:35:13 + | +LL | let _ = test_i64().min(i64::MAX); // signed with MAX and function + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `test_i64()` + +error: aborting due to 18 previous errors + diff --git a/triagebot.toml b/triagebot.toml index 96085bcf9ee2..ab2fb1a32919 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -19,7 +19,6 @@ new_pr = true [assign] contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" -users_on_vacation = ["blyxyas"] [assign.owners] "/.github" = ["@flip1995"]