diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs index d52ad1c6f..ff460a3fd 100644 --- a/clippy_lints/src/casts/cast_lossless.rs +++ b/clippy_lints/src/casts/cast_lossless.rs @@ -1,19 +1,21 @@ use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::in_constant; -use clippy_utils::source::{snippet_opt, snippet_with_applicability}; +use clippy_utils::source::snippet_opt; +use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_isize_or_usize; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, QPath, TyKind}; +use rustc_hir::{Expr, QPath, TyKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, FloatTy, Ty, UintTy}; +use rustc_middle::ty::{self, FloatTy, Ty}; +use rustc_span::hygiene; use super::{utils, CAST_LOSSLESS}; pub(super) fn check( cx: &LateContext<'_>, expr: &Expr<'_>, - cast_op: &Expr<'_>, + cast_from_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, cast_to_hir: &rustc_hir::Ty<'_>, @@ -23,64 +25,54 @@ pub(super) fn check( return; } - // The suggestion is to use a function call, so if the original expression - // has parens on the outside, they are no longer needed. - let mut app = Applicability::MachineApplicable; - let opt = snippet_opt(cx, cast_op.span.source_callsite()); - let sugg = opt.as_ref().map_or_else( - || { - app = Applicability::HasPlaceholders; - ".." - }, - |snip| { - if should_strip_parens(cast_op, snip) { - &snip[1..snip.len() - 1] - } else { - snip.as_str() - } - }, - ); - - // Display the type alias instead of the aliased type. Fixes #11285 - // - // FIXME: Once `lazy_type_alias` is stabilized(?) we should use `rustc_middle` types instead, - // this will allow us to display the right type with `cast_from` as well. - let cast_to_fmt = if let TyKind::Path(QPath::Resolved(None, path)) = cast_to_hir.kind - // It's a bit annoying but the turbofish is optional for types. A type in an `as` cast - // shouldn't have these if they're primitives, which are the only things we deal with. - // - // This could be removed for performance if this check is determined to have a pretty major - // effect. - && path.segments.iter().all(|segment| segment.args.is_none()) - { - snippet_with_applicability(cx, cast_to_hir.span, "..", &mut app) - } else { - cast_to.to_string().into() - }; - - let message = if cast_from.is_bool() { - format!("casting `{cast_from}` to `{cast_to_fmt}` is more cleanly stated with `{cast_to_fmt}::from(_)`") - } else { - format!("casting `{cast_from}` to `{cast_to_fmt}` may become silently lossy if you later change the type") - }; - - span_lint_and_sugg( + span_lint_and_then( cx, CAST_LOSSLESS, expr.span, - message, - "try", - format!("{cast_to_fmt}::from({sugg})"), - app, + format!("casts from `{cast_from}` to `{cast_to}` can be expressed infallibly using `From`"), + |diag| { + diag.help("an `as` cast can become silently lossy if the types change in the future"); + let mut applicability = Applicability::MachineApplicable; + let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "", &mut applicability); + let Some(ty) = snippet_opt(cx, hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt())) else { + return; + }; + match cast_to_hir.kind { + TyKind::Infer => { + diag.span_suggestion_verbose( + expr.span, + "use `Into::into` instead", + format!("{}.into()", from_sugg.maybe_par()), + applicability, + ); + }, + // Don't suggest `A<_>::B::From(x)` or `macro!()::from(x)` + kind if matches!(kind, TyKind::Path(QPath::Resolved(_, path)) if path.segments.iter().any(|s| s.args.is_some())) + || !cast_to_hir.span.eq_ctxt(expr.span) => + { + diag.span_suggestion_verbose( + expr.span, + format!("use `<{ty}>::from` instead"), + format!("<{ty}>::from({from_sugg})"), + applicability, + ); + }, + _ => { + diag.span_suggestion_verbose( + expr.span, + format!("use `{ty}::from` instead"), + format!("{ty}::from({from_sugg})"), + applicability, + ); + }, + } + }, ); } fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, 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 destination is u128, do not lint because source type cannot be larger - // If source is bool, still lint due to the lint message differing (refers to style) - if in_constant(cx, expr.hir_id) || (!cast_from.is_bool() && matches!(cast_to.kind(), ty::Uint(UintTy::U128))) { + if in_constant(cx, expr.hir_id) { return false; } @@ -110,12 +102,3 @@ fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to }, } } - -fn should_strip_parens(cast_expr: &Expr<'_>, snip: &str) -> bool { - if let ExprKind::Binary(_, _, _) = cast_expr.kind { - if snip.starts_with('(') && snip.ends_with(')') { - return true; - } - } - false -} diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 773731113..c31716fbc 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -763,45 +763,45 @@ impl<'tcx> LateLintPass<'tcx> for Casts { return; } - if let ExprKind::Cast(cast_expr, cast_to_hir) = expr.kind { + if let ExprKind::Cast(cast_from_expr, cast_to_hir) = expr.kind { if is_hir_ty_cfg_dependant(cx, cast_to_hir) { return; } let (cast_from, cast_to) = ( - cx.typeck_results().expr_ty(cast_expr), + cx.typeck_results().expr_ty(cast_from_expr), cx.typeck_results().expr_ty(expr), ); - if !expr.span.from_expansion() && unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) { + 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_expr, cast_to, &self.msrv); - ptr_cast_constness::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); - as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to); - fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to); - fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to); - fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to); - zero_ptr::check(cx, expr, cast_expr, cast_to_hir); + 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); + fn_to_numeric_cast_with_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to); + zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir); if cast_to.is_numeric() { - cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span); + cast_possible_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir.span); if cast_from.is_numeric() { 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_expr, cast_from, cast_to); - cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); - cast_nan_to_int::check(cx, expr, cast_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_nan_to_int::check(cx, expr, cast_from_expr, cast_from, cast_to); } - cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir, &self.msrv); - cast_enum_constructor::check(cx, expr, cast_expr, cast_from); + 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); if self.msrv.meets(msrvs::PTR_FROM_REF) { - ref_as_ptr::check(cx, expr, cast_expr, cast_to_hir); + ref_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir); } else if self.msrv.meets(msrvs::BORROW_AS_PTR) { - borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir); + borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir); } } diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 6319c7bfa..0f86d89c9 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -52,7 +52,8 @@ impl Display for Sugg<'_> { impl<'a> Sugg<'a> { /// Prepare a suggestion from an expression. pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option { - let get_snippet = |span| snippet(cx, span, ""); + let ctxt = expr.span.ctxt(); + let get_snippet = |span| snippet_with_context(cx, span, ctxt, "", &mut Applicability::Unspecified).0; snippet_opt(cx, expr.span).map(|_| Self::hir_from_snippet(expr, get_snippet)) } @@ -100,7 +101,9 @@ impl<'a> Sugg<'a> { applicability: &mut Applicability, ) -> Self { if expr.span.ctxt() == ctxt { - Self::hir_from_snippet(expr, |span| snippet(cx, span, default)) + Self::hir_from_snippet(expr, |span| { + snippet_with_context(cx, span, ctxt, default, applicability).0 + }) } else { let (snip, _) = snippet_with_context(cx, expr.span, ctxt, default, applicability); Sugg::NonParen(snip) @@ -109,7 +112,7 @@ impl<'a> Sugg<'a> { /// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*` /// function variants of `Sugg`, since these use different snippet functions. - fn hir_from_snippet(expr: &hir::Expr<'_>, get_snippet: impl Fn(Span) -> Cow<'a, str>) -> Self { + 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, diff --git a/tests/ui/cast_lossless_bool.stderr b/tests/ui/cast_lossless_bool.stderr index b47b35461..82d6b2e4b 100644 --- a/tests/ui/cast_lossless_bool.stderr +++ b/tests/ui/cast_lossless_bool.stderr @@ -1,95 +1,184 @@ -error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)` +error: casts from `bool` to `u8` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:8:13 | LL | let _ = true as u8; - | ^^^^^^^^^^ help: try: `u8::from(true)` + | ^^^^^^^^^^ | + = help: an `as` cast can become silently lossy if the types change in the future = note: `-D clippy::cast-lossless` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` +help: use `u8::from` instead + | +LL | let _ = u8::from(true); + | ~~~~~~~~~~~~~~ -error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)` +error: casts from `bool` to `u16` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:9:13 | LL | let _ = true as u16; - | ^^^^^^^^^^^ help: try: `u16::from(true)` + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u16::from` instead + | +LL | let _ = u16::from(true); + | ~~~~~~~~~~~~~~~ -error: casting `bool` to `u32` is more cleanly stated with `u32::from(_)` +error: casts from `bool` to `u32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:10:13 | LL | let _ = true as u32; - | ^^^^^^^^^^^ help: try: `u32::from(true)` + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u32::from` instead + | +LL | let _ = u32::from(true); + | ~~~~~~~~~~~~~~~ -error: casting `bool` to `u64` is more cleanly stated with `u64::from(_)` +error: casts from `bool` to `u64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:11:13 | LL | let _ = true as u64; - | ^^^^^^^^^^^ help: try: `u64::from(true)` + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u64::from` instead + | +LL | let _ = u64::from(true); + | ~~~~~~~~~~~~~~~ -error: casting `bool` to `u128` is more cleanly stated with `u128::from(_)` +error: casts from `bool` to `u128` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:12:13 | LL | let _ = true as u128; - | ^^^^^^^^^^^^ help: try: `u128::from(true)` + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u128::from` instead + | +LL | let _ = u128::from(true); + | ~~~~~~~~~~~~~~~~ -error: casting `bool` to `usize` is more cleanly stated with `usize::from(_)` +error: casts from `bool` to `usize` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:13:13 | LL | let _ = true as usize; - | ^^^^^^^^^^^^^ help: try: `usize::from(true)` + | ^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `usize::from` instead + | +LL | let _ = usize::from(true); + | ~~~~~~~~~~~~~~~~~ -error: casting `bool` to `i8` is more cleanly stated with `i8::from(_)` +error: casts from `bool` to `i8` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:15:13 | LL | let _ = true as i8; - | ^^^^^^^^^^ help: try: `i8::from(true)` + | ^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i8::from` instead + | +LL | let _ = i8::from(true); + | ~~~~~~~~~~~~~~ -error: casting `bool` to `i16` is more cleanly stated with `i16::from(_)` +error: casts from `bool` to `i16` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:16:13 | LL | let _ = true as i16; - | ^^^^^^^^^^^ help: try: `i16::from(true)` + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i16::from` instead + | +LL | let _ = i16::from(true); + | ~~~~~~~~~~~~~~~ -error: casting `bool` to `i32` is more cleanly stated with `i32::from(_)` +error: casts from `bool` to `i32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:17:13 | LL | let _ = true as i32; - | ^^^^^^^^^^^ help: try: `i32::from(true)` + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i32::from` instead + | +LL | let _ = i32::from(true); + | ~~~~~~~~~~~~~~~ -error: casting `bool` to `i64` is more cleanly stated with `i64::from(_)` +error: casts from `bool` to `i64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:18:13 | LL | let _ = true as i64; - | ^^^^^^^^^^^ help: try: `i64::from(true)` + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i64::from` instead + | +LL | let _ = i64::from(true); + | ~~~~~~~~~~~~~~~ -error: casting `bool` to `i128` is more cleanly stated with `i128::from(_)` +error: casts from `bool` to `i128` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:19:13 | LL | let _ = true as i128; - | ^^^^^^^^^^^^ help: try: `i128::from(true)` + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | let _ = i128::from(true); + | ~~~~~~~~~~~~~~~~ -error: casting `bool` to `isize` is more cleanly stated with `isize::from(_)` +error: casts from `bool` to `isize` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:20:13 | LL | let _ = true as isize; - | ^^^^^^^^^^^^^ help: try: `isize::from(true)` + | ^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `isize::from` instead + | +LL | let _ = isize::from(true); + | ~~~~~~~~~~~~~~~~~ -error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)` +error: casts from `bool` to `u16` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:23:13 | LL | let _ = (true | false) as u16; - | ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)` + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u16::from` instead + | +LL | let _ = u16::from(true | false); + | ~~~~~~~~~~~~~~~~~~~~~~~ -error: casting `bool` to `U8` is more cleanly stated with `U8::from(_)` +error: casts from `bool` to `u8` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:25:13 | LL | let _ = true as U8; - | ^^^^^^^^^^ help: try: `U8::from(true)` + | ^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `U8::from` instead + | +LL | let _ = U8::from(true); + | ~~~~~~~~~~~~~~ -error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)` +error: casts from `bool` to `u8` can be expressed infallibly using `From` --> tests/ui/cast_lossless_bool.rs:53:13 | LL | let _ = true as u8; - | ^^^^^^^^^^ help: try: `u8::from(true)` + | ^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u8::from` instead + | +LL | let _ = u8::from(true); + | ~~~~~~~~~~~~~~ error: aborting due to 15 previous errors diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index f2ba4e3b9..b36f8bcec 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,83 +1,160 @@ -error: casting `i8` to `f32` may become silently lossy if you later change the type +error: casts from `i8` to `f32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:12:13 | LL | let _ = x0 as f32; - | ^^^^^^^^^ help: try: `f32::from(x0)` + | ^^^^^^^^^ | + = help: an `as` cast can become silently lossy if the types change in the future = note: `-D clippy::cast-lossless` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` +help: use `f32::from` instead + | +LL | let _ = f32::from(x0); + | ~~~~~~~~~~~~~ -error: casting `i8` to `f64` may become silently lossy if you later change the type +error: casts from `i8` to `f64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:13:13 | LL | let _ = x0 as f64; - | ^^^^^^^^^ help: try: `f64::from(x0)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f64::from` instead + | +LL | let _ = f64::from(x0); + | ~~~~~~~~~~~~~ -error: casting `i8` to `F32` may become silently lossy if you later change the type +error: casts from `i8` to `f32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:14:13 | LL | let _ = x0 as F32; - | ^^^^^^^^^ help: try: `F32::from(x0)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `F32::from` instead + | +LL | let _ = F32::from(x0); + | ~~~~~~~~~~~~~ -error: casting `i8` to `F64` may become silently lossy if you later change the type +error: casts from `i8` to `f64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:15:13 | LL | let _ = x0 as F64; - | ^^^^^^^^^ help: try: `F64::from(x0)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `F64::from` instead + | +LL | let _ = F64::from(x0); + | ~~~~~~~~~~~~~ -error: casting `u8` to `f32` may become silently lossy if you later change the type +error: casts from `u8` to `f32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:17:13 | LL | let _ = x1 as f32; - | ^^^^^^^^^ help: try: `f32::from(x1)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f32::from` instead + | +LL | let _ = f32::from(x1); + | ~~~~~~~~~~~~~ -error: casting `u8` to `f64` may become silently lossy if you later change the type +error: casts from `u8` to `f64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:18:13 | LL | let _ = x1 as f64; - | ^^^^^^^^^ help: try: `f64::from(x1)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f64::from` instead + | +LL | let _ = f64::from(x1); + | ~~~~~~~~~~~~~ -error: casting `i16` to `f32` may become silently lossy if you later change the type +error: casts from `i16` to `f32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:20:13 | LL | let _ = x2 as f32; - | ^^^^^^^^^ help: try: `f32::from(x2)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f32::from` instead + | +LL | let _ = f32::from(x2); + | ~~~~~~~~~~~~~ -error: casting `i16` to `f64` may become silently lossy if you later change the type +error: casts from `i16` to `f64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:21:13 | LL | let _ = x2 as f64; - | ^^^^^^^^^ help: try: `f64::from(x2)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f64::from` instead + | +LL | let _ = f64::from(x2); + | ~~~~~~~~~~~~~ -error: casting `u16` to `f32` may become silently lossy if you later change the type +error: casts from `u16` to `f32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:23:13 | LL | let _ = x3 as f32; - | ^^^^^^^^^ help: try: `f32::from(x3)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f32::from` instead + | +LL | let _ = f32::from(x3); + | ~~~~~~~~~~~~~ -error: casting `u16` to `f64` may become silently lossy if you later change the type +error: casts from `u16` to `f64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:24:13 | LL | let _ = x3 as f64; - | ^^^^^^^^^ help: try: `f64::from(x3)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f64::from` instead + | +LL | let _ = f64::from(x3); + | ~~~~~~~~~~~~~ -error: casting `i32` to `f64` may become silently lossy if you later change the type +error: casts from `i32` to `f64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:26:13 | LL | let _ = x4 as f64; - | ^^^^^^^^^ help: try: `f64::from(x4)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f64::from` instead + | +LL | let _ = f64::from(x4); + | ~~~~~~~~~~~~~ -error: casting `u32` to `f64` may become silently lossy if you later change the type +error: casts from `u32` to `f64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:28:13 | LL | let _ = x5 as f64; - | ^^^^^^^^^ help: try: `f64::from(x5)` + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f64::from` instead + | +LL | let _ = f64::from(x5); + | ~~~~~~~~~~~~~ -error: casting `f32` to `f64` may become silently lossy if you later change the type +error: casts from `f32` to `f64` can be expressed infallibly using `From` --> tests/ui/cast_lossless_float.rs:31:13 | LL | let _ = 1.0f32 as f64; - | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)` + | ^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `f64::from` instead + | +LL | let _ = f64::from(1.0f32); + | ~~~~~~~~~~~~~~~~~ error: aborting due to 13 previous errors diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed index 291556a97..cdb065678 100644 --- a/tests/ui/cast_lossless_integer.fixed +++ b/tests/ui/cast_lossless_integer.fixed @@ -1,39 +1,93 @@ #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] -type I64 = i64; -type U128 = u128; +type I64Alias = i64; fn main() { // Test clippy::cast_lossless with casts to integer types - let _ = i16::from(1i8); - let _ = i32::from(1i8); - let _ = i64::from(1i8); - let _ = i16::from(1u8); - let _ = i32::from(1u8); - let _ = i64::from(1u8); - let _ = u16::from(1u8); - let _ = u32::from(1u8); - let _ = u64::from(1u8); - let _ = i32::from(1i16); - let _ = i64::from(1i16); - let _ = i32::from(1u16); - let _ = i64::from(1u16); - let _ = u32::from(1u16); - let _ = u64::from(1u16); - let _ = i64::from(1i32); - let _ = i64::from(1u32); - let _ = u64::from(1u32); + 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 + + i128::from(0i64); + //~^ cast_lossless // Test with an expression wrapped in parens let _ = u16::from(1u8 + 1u8); + //~^ cast_lossless - let _ = I64::from(1i8); + let _ = I64Alias::from(1i8); + //~^ cast_lossless - // Do not lint if destination type is u128 - // see https://github.com/rust-lang/rust-clippy/issues/12492 - let _ = 1u8 as u128; - let _ = 1u8 as U128; + 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 } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, @@ -68,5 +122,30 @@ 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 } + +fn issue12695() { + macro_rules! in_macro { + () => { + u32::from(1u8) + //~^ cast_lossless + }; + } + + let _ = in_macro!(); +} + +fn ty_from_macro() { + macro_rules! ty { + () => { + u32 + }; + } + + let _ = ::from(0u8); +} + +const IN_CONST: u64 = 0u8 as u64; diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index a917c7a37..1f510b1a3 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -1,39 +1,93 @@ #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] -type I64 = i64; -type U128 = u128; +type I64Alias = i64; fn main() { // Test clippy::cast_lossless with casts to integer types - let _ = 1i8 as i16; - let _ = 1i8 as i32; - let _ = 1i8 as i64; - let _ = 1u8 as i16; - let _ = 1u8 as i32; - let _ = 1u8 as i64; - let _ = 1u8 as u16; - let _ = 1u8 as u32; - let _ = 1u8 as u64; - let _ = 1i16 as i32; - let _ = 1i16 as i64; - let _ = 1u16 as i32; - let _ = 1u16 as i64; - let _ = 1u16 as u32; - let _ = 1u16 as u64; - let _ = 1i32 as i64; - let _ = 1u32 as i64; - let _ = 1u32 as u64; + 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 + + 0i64 as i128; + //~^ cast_lossless // Test with an expression wrapped in parens let _ = (1u8 + 1u8) as u16; + //~^ cast_lossless - let _ = 1i8 as I64; + let _ = 1i8 as I64Alias; + //~^ cast_lossless - // Do not lint if destination type is u128 - // see https://github.com/rust-lang/rust-clippy/issues/12492 - let _ = 1u8 as u128; - let _ = 1u8 as U128; + 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 } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, @@ -68,5 +122,30 @@ 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 } + +fn issue12695() { + macro_rules! in_macro { + () => { + 1u8 as u32 + //~^ cast_lossless + }; + } + + let _ = in_macro!(); +} + +fn ty_from_macro() { + macro_rules! ty { + () => { + u32 + }; + } + + let _ = 0u8 as ty!(); +} + +const IN_CONST: u64 = 0u8 as u64; diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index aaece9392..c93ecb8fb 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,137 +1,488 @@ -error: casting `i8` to `i16` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:9:13 +error: casts from `u8` to `u16` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:8:5 | -LL | let _ = 1i8 as i16; - | ^^^^^^^^^^ help: try: `i16::from(1i8)` +LL | 0u8 as u16; + | ^^^^^^^^^^ | + = help: an `as` cast can become silently lossy if the types change in the future = note: `-D clippy::cast-lossless` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` - -error: casting `i8` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:10:13 +help: use `u16::from` instead | -LL | let _ = 1i8 as i32; - | ^^^^^^^^^^ help: try: `i32::from(1i8)` +LL | u16::from(0u8); + | ~~~~~~~~~~~~~~ -error: casting `i8` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:11:13 +error: casts from `u8` to `i16` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:10:5 | -LL | let _ = 1i8 as i64; - | ^^^^^^^^^^ help: try: `i64::from(1i8)` - -error: casting `u8` to `i16` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:12:13 +LL | 0u8 as i16; + | ^^^^^^^^^^ | -LL | let _ = 1u8 as i16; - | ^^^^^^^^^^ help: try: `i16::from(1u8)` - -error: casting `u8` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:13:13 + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i16::from` instead | -LL | let _ = 1u8 as i32; - | ^^^^^^^^^^ help: try: `i32::from(1u8)` +LL | i16::from(0u8); + | ~~~~~~~~~~~~~~ -error: casting `u8` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:14:13 +error: casts from `u8` to `u32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:12:5 | -LL | let _ = 1u8 as i64; - | ^^^^^^^^^^ help: try: `i64::from(1u8)` - -error: casting `u8` to `u16` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:15:13 +LL | 0u8 as u32; + | ^^^^^^^^^^ | -LL | let _ = 1u8 as u16; - | ^^^^^^^^^^ help: try: `u16::from(1u8)` - -error: casting `u8` to `u32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:16:13 + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u32::from` instead | -LL | let _ = 1u8 as u32; - | ^^^^^^^^^^ help: try: `u32::from(1u8)` +LL | u32::from(0u8); + | ~~~~~~~~~~~~~~ -error: casting `u8` to `u64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:17:13 +error: casts from `u8` to `i32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:14:5 | -LL | let _ = 1u8 as u64; - | ^^^^^^^^^^ help: try: `u64::from(1u8)` - -error: casting `i16` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:18:13 +LL | 0u8 as i32; + | ^^^^^^^^^^ | -LL | let _ = 1i16 as i32; - | ^^^^^^^^^^^ help: try: `i32::from(1i16)` - -error: casting `i16` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:19:13 + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i32::from` instead | -LL | let _ = 1i16 as i64; - | ^^^^^^^^^^^ help: try: `i64::from(1i16)` +LL | i32::from(0u8); + | ~~~~~~~~~~~~~~ -error: casting `u16` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:20:13 +error: casts from `u8` to `u64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:16:5 | -LL | let _ = 1u16 as i32; - | ^^^^^^^^^^^ help: try: `i32::from(1u16)` - -error: casting `u16` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:21:13 +LL | 0u8 as u64; + | ^^^^^^^^^^ | -LL | let _ = 1u16 as i64; - | ^^^^^^^^^^^ help: try: `i64::from(1u16)` - -error: casting `u16` to `u32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:22:13 + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u64::from` instead | -LL | let _ = 1u16 as u32; - | ^^^^^^^^^^^ help: try: `u32::from(1u16)` +LL | u64::from(0u8); + | ~~~~~~~~~~~~~~ -error: casting `u16` to `u64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:23:13 +error: casts from `u8` to `i64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:18:5 | -LL | let _ = 1u16 as u64; - | ^^^^^^^^^^^ help: try: `u64::from(1u16)` - -error: casting `i32` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:24:13 +LL | 0u8 as i64; + | ^^^^^^^^^^ | -LL | let _ = 1i32 as i64; - | ^^^^^^^^^^^ help: try: `i64::from(1i32)` - -error: casting `u32` to `i64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:25:13 + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i64::from` instead | -LL | let _ = 1u32 as i64; - | ^^^^^^^^^^^ help: try: `i64::from(1u32)` +LL | i64::from(0u8); + | ~~~~~~~~~~~~~~ -error: casting `u32` to `u64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:26:13 +error: casts from `u8` to `u128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:20:5 | -LL | let _ = 1u32 as u64; - | ^^^^^^^^^^^ help: try: `u64::from(1u32)` +LL | 0u8 as u128; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u128::from` instead + | +LL | u128::from(0u8); + | ~~~~~~~~~~~~~~~ -error: casting `u8` to `u16` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:29:13 +error: casts from `u8` to `i128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:22:5 + | +LL | 0u8 as i128; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | i128::from(0u8); + | ~~~~~~~~~~~~~~~ + +error: casts from `u16` to `u32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:25:5 + | +LL | 0u16 as u32; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u32::from` instead + | +LL | u32::from(0u16); + | ~~~~~~~~~~~~~~~ + +error: casts from `u16` to `i32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:27:5 + | +LL | 0u16 as i32; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i32::from` instead + | +LL | i32::from(0u16); + | ~~~~~~~~~~~~~~~ + +error: casts from `u16` to `u64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:29:5 + | +LL | 0u16 as u64; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u64::from` instead + | +LL | u64::from(0u16); + | ~~~~~~~~~~~~~~~ + +error: casts from `u16` to `i64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:31:5 + | +LL | 0u16 as i64; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i64::from` instead + | +LL | i64::from(0u16); + | ~~~~~~~~~~~~~~~ + +error: casts from `u16` to `u128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:33:5 + | +LL | 0u16 as u128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u128::from` instead + | +LL | u128::from(0u16); + | ~~~~~~~~~~~~~~~~ + +error: casts from `u16` to `i128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:35:5 + | +LL | 0u16 as i128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | i128::from(0u16); + | ~~~~~~~~~~~~~~~~ + +error: casts from `u32` to `u64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:38:5 + | +LL | 0u32 as u64; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u64::from` instead + | +LL | u64::from(0u32); + | ~~~~~~~~~~~~~~~ + +error: casts from `u32` to `i64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:40:5 + | +LL | 0u32 as i64; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i64::from` instead + | +LL | i64::from(0u32); + | ~~~~~~~~~~~~~~~ + +error: casts from `u32` to `u128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:42:5 + | +LL | 0u32 as u128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u128::from` instead + | +LL | u128::from(0u32); + | ~~~~~~~~~~~~~~~~ + +error: casts from `u32` to `i128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:44:5 + | +LL | 0u32 as i128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | i128::from(0u32); + | ~~~~~~~~~~~~~~~~ + +error: casts from `u64` to `u128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:47:5 + | +LL | 0u64 as u128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u128::from` instead + | +LL | u128::from(0u64); + | ~~~~~~~~~~~~~~~~ + +error: casts from `u64` to `i128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:49:5 + | +LL | 0u64 as i128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | i128::from(0u64); + | ~~~~~~~~~~~~~~~~ + +error: casts from `i8` to `i16` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:52:5 + | +LL | 0i8 as i16; + | ^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i16::from` instead + | +LL | i16::from(0i8); + | ~~~~~~~~~~~~~~ + +error: casts from `i8` to `i32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:54:5 + | +LL | 0i8 as i32; + | ^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i32::from` instead + | +LL | i32::from(0i8); + | ~~~~~~~~~~~~~~ + +error: casts from `i8` to `i64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:56:5 + | +LL | 0i8 as i64; + | ^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i64::from` instead + | +LL | i64::from(0i8); + | ~~~~~~~~~~~~~~ + +error: casts from `i8` to `i128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:58:5 + | +LL | 0i8 as i128; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | i128::from(0i8); + | ~~~~~~~~~~~~~~~ + +error: casts from `i16` to `i32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:61:5 + | +LL | 0i16 as i32; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i32::from` instead + | +LL | i32::from(0i16); + | ~~~~~~~~~~~~~~~ + +error: casts from `i16` to `i64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:63:5 + | +LL | 0i16 as i64; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i64::from` instead + | +LL | i64::from(0i16); + | ~~~~~~~~~~~~~~~ + +error: casts from `i16` to `i128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:65:5 + | +LL | 0i16 as i128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | i128::from(0i16); + | ~~~~~~~~~~~~~~~~ + +error: casts from `i32` to `i64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:68:5 + | +LL | 0i32 as i64; + | ^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i64::from` instead + | +LL | i64::from(0i32); + | ~~~~~~~~~~~~~~~ + +error: casts from `i32` to `i128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:70:5 + | +LL | 0i32 as i128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | i128::from(0i32); + | ~~~~~~~~~~~~~~~~ + +error: casts from `i64` to `i128` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:73:5 + | +LL | 0i64 as i128; + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i128::from` instead + | +LL | i128::from(0i64); + | ~~~~~~~~~~~~~~~~ + +error: casts from `u8` to `u16` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:77:13 | LL | let _ = (1u8 + 1u8) as u16; - | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` - -error: casting `i8` to `I64` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:31:13 + | ^^^^^^^^^^^^^^^^^^ | -LL | let _ = 1i8 as I64; - | ^^^^^^^^^^ help: try: `I64::from(1i8)` + = help: an `as` cast can become silently lossy if the types change in the future +help: use `u16::from` instead + | +LL | let _ = u16::from(1u8 + 1u8); + | ~~~~~~~~~~~~~~~~~~~~ -error: casting `i8` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:70:13 +error: casts from `i8` to `i64` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:80:13 + | +LL | let _ = 1i8 as I64Alias; + | ^^^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `I64Alias::from` instead + | +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 + | +LL | let _: u16 = 0u8 as _; + | ^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `Into::into` instead + | +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 + | +LL | let _: i16 = -1i8 as _; + | ^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `Into::into` instead + | +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 + | +LL | let _: u16 = (1u8 + 2) as _; + | ^^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `Into::into` instead + | +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 + | +LL | let _: u32 = 1i8 as u16 as _; + | ^^^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `Into::into` instead + | +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 | LL | let _ = sign_cast!(x, u8, i8) as i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i32::from` instead + | +LL | let _ = i32::from(sign_cast!(x, u8, i8)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: casting `i8` to `i32` may become silently lossy if you later change the type - --> tests/ui/cast_lossless_integer.rs:71:13 +error: casts from `i8` to `i32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:126:13 | LL | let _ = (sign_cast!(x, u8, i8) + 1) as i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8) + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `i32::from` instead + | +LL | let _ = i32::from(sign_cast!(x, u8, i8) + 1); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 22 previous errors +error: casts from `u8` to `u32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:133:13 + | +LL | 1u8 as u32 + | ^^^^^^^^^^ +... +LL | let _ = in_macro!(); + | ----------- in this macro invocation + | + = help: an `as` cast can become silently lossy if the types change in the future + = note: this error originates in the macro `in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use `u32::from` instead + | +LL | u32::from(1u8) + | + +error: casts from `u8` to `u32` can be expressed infallibly using `From` + --> tests/ui/cast_lossless_integer.rs:148:13 + | +LL | let _ = 0u8 as ty!(); + | ^^^^^^^^^^^^ + | + = help: an `as` cast can become silently lossy if the types change in the future +help: use `::from` instead + | +LL | let _ = ::from(0u8); + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 40 previous errors diff --git a/tests/ui/floating_point_powf.fixed b/tests/ui/floating_point_powf.fixed index a44938fdf..25f09a637 100644 --- a/tests/ui/floating_point_powf.fixed +++ b/tests/ui/floating_point_powf.fixed @@ -25,6 +25,14 @@ fn main() { let _ = 1.5_f64.sqrt(); let _ = 1.5_f64.powi(3); + macro_rules! m { + ($e:expr) => { + 5.5 - $e + }; + } + + let _ = (1f32 + m!(2.0)).exp2(); + // 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 80f6c1791..9e9878de4 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -25,6 +25,14 @@ fn main() { let _ = 1.5_f64.powf(1.0 / 2.0); let _ = 1.5_f64.powf(3.0); + macro_rules! m { + ($e:expr) => { + 5.5 - $e + }; + } + + let _ = 2f32.powf(1f32 + m!(2.0)); + // 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 671383401..c944f14fa 100644 --- a/tests/ui/floating_point_powf.stderr +++ b/tests/ui/floating_point_powf.stderr @@ -119,76 +119,82 @@ 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:35:13 + --> tests/ui/floating_point_powf.rs:34: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 | 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:36:13 + --> tests/ui/floating_point_powf.rs:44: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:37:13 + --> tests/ui/floating_point_powf.rs:45: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:38:13 + --> tests/ui/floating_point_powf.rs:46: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:39:13 + --> tests/ui/floating_point_powf.rs:47: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:40:13 + --> tests/ui/floating_point_powf.rs:48: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:41:13 + --> tests/ui/floating_point_powf.rs:49: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:42:13 + --> tests/ui/floating_point_powf.rs:50: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:43:13 + --> tests/ui/floating_point_powf.rs:51: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:44:13 + --> tests/ui/floating_point_powf.rs:52: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:45:13 + --> tests/ui/floating_point_powf.rs:53: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:46:13 + --> tests/ui/floating_point_powf.rs:54:13 | LL | let _ = x.powf(2_147_483_647.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)` -error: aborting due to 31 previous errors +error: aborting due to 32 previous errors diff --git a/tests/ui/types.fixed b/tests/ui/types.fixed deleted file mode 100644 index 6f1f55f0e..000000000 --- a/tests/ui/types.fixed +++ /dev/null @@ -1,13 +0,0 @@ -#![allow(dead_code, unused_variables)] -#![warn(clippy::cast_lossless)] - -// should not warn on lossy casting in constant types -// because not supported yet -const C: i32 = 42; -const C_I64: i64 = C as i64; - -fn main() { - // should suggest i64::from(c) - let c: i32 = 42; - let c_i64: i64 = i64::from(c); -} diff --git a/tests/ui/types.rs b/tests/ui/types.rs deleted file mode 100644 index 960aee460..000000000 --- a/tests/ui/types.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![allow(dead_code, unused_variables)] -#![warn(clippy::cast_lossless)] - -// should not warn on lossy casting in constant types -// because not supported yet -const C: i32 = 42; -const C_I64: i64 = C as i64; - -fn main() { - // should suggest i64::from(c) - let c: i32 = 42; - let c_i64: i64 = c as i64; -} diff --git a/tests/ui/types.stderr b/tests/ui/types.stderr deleted file mode 100644 index 02e750181..000000000 --- a/tests/ui/types.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: casting `i32` to `i64` may become silently lossy if you later change the type - --> tests/ui/types.rs:12:22 - | -LL | let c_i64: i64 = c as i64; - | ^^^^^^^^ help: try: `i64::from(c)` - | - = note: `-D clippy::cast-lossless` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` - -error: aborting due to 1 previous error -