Lint casts to u128 in cast_lossless

This commit is contained in:
Alex Macleod 2024-07-22 19:00:58 +00:00
parent 1807580a49
commit 6d28e1a954
14 changed files with 985 additions and 339 deletions

View file

@ -1,19 +1,21 @@
use clippy_config::msrvs::{self, Msrv}; 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::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 clippy_utils::ty::is_isize_or_usize;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, QPath, TyKind}; use rustc_hir::{Expr, QPath, TyKind};
use rustc_lint::LateContext; 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}; use super::{utils, CAST_LOSSLESS};
pub(super) fn check( pub(super) fn check(
cx: &LateContext<'_>, cx: &LateContext<'_>,
expr: &Expr<'_>, expr: &Expr<'_>,
cast_op: &Expr<'_>, cast_from_expr: &Expr<'_>,
cast_from: Ty<'_>, cast_from: Ty<'_>,
cast_to: Ty<'_>, cast_to: Ty<'_>,
cast_to_hir: &rustc_hir::Ty<'_>, cast_to_hir: &rustc_hir::Ty<'_>,
@ -23,64 +25,54 @@ pub(super) fn check(
return; return;
} }
// The suggestion is to use a function call, so if the original expression span_lint_and_then(
// 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(
cx, cx,
CAST_LOSSLESS, CAST_LOSSLESS,
expr.span, expr.span,
message, format!("casts from `{cast_from}` to `{cast_to}` can be expressed infallibly using `From`"),
"try", |diag| {
format!("{cast_to_fmt}::from({sugg})"), diag.help("an `as` cast can become silently lossy if the types change in the future");
app, let mut applicability = Applicability::MachineApplicable;
let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "<from>", &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 { 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). // Do not suggest using From in consts/statics until it is valid to do so (see #2267).
// if in_constant(cx, expr.hir_id) {
// 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))) {
return false; 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
}

View file

@ -763,45 +763,45 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
return; 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) { if is_hir_ty_cfg_dependant(cx, cast_to_hir) {
return; return;
} }
let (cast_from, cast_to) = ( 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), 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; return;
} }
cast_slice_from_raw_parts::check(cx, expr, cast_expr, 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_expr, cast_from, 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_expr, cast_to); as_ptr_cast_mut::check(cx, expr, cast_from_expr, cast_to);
fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, 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_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_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_expr, cast_to_hir); zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
if cast_to.is_numeric() { 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() { if cast_from.is_numeric() {
cast_possible_wrap::check(cx, expr, cast_from, cast_to); cast_possible_wrap::check(cx, expr, cast_from, cast_to);
cast_precision_loss::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_sign_loss::check(cx, expr, cast_from_expr, cast_from, cast_to);
cast_abs_to_unsigned::check(cx, expr, cast_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_expr, cast_from, cast_to); 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_lossless::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir, &self.msrv);
cast_enum_constructor::check(cx, expr, cast_expr, cast_from); cast_enum_constructor::check(cx, expr, cast_from_expr, cast_from);
} }
as_underscore::check(cx, expr, cast_to_hir); as_underscore::check(cx, expr, cast_to_hir);
if self.msrv.meets(msrvs::PTR_FROM_REF) { 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) { } 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);
} }
} }

View file

@ -52,7 +52,8 @@ impl Display for Sugg<'_> {
impl<'a> Sugg<'a> { impl<'a> Sugg<'a> {
/// Prepare a suggestion from an expression. /// Prepare a suggestion from an expression.
pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Self> { pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Self> {
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)) snippet_opt(cx, expr.span).map(|_| Self::hir_from_snippet(expr, get_snippet))
} }
@ -100,7 +101,9 @@ impl<'a> Sugg<'a> {
applicability: &mut Applicability, applicability: &mut Applicability,
) -> Self { ) -> Self {
if expr.span.ctxt() == ctxt { 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 { } else {
let (snip, _) = snippet_with_context(cx, expr.span, ctxt, default, applicability); let (snip, _) = snippet_with_context(cx, expr.span, ctxt, default, applicability);
Sugg::NonParen(snip) 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_*` /// 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. /// 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) { if let Some(range) = higher::Range::hir(expr) {
let op = match range.limits { let op = match range.limits {
ast::RangeLimits::HalfOpen => AssocOp::DotDot, ast::RangeLimits::HalfOpen => AssocOp::DotDot,

View file

@ -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 --> tests/ui/cast_lossless_bool.rs:8:13
| |
LL | let _ = true as u8; 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` = note: `-D clippy::cast-lossless` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` = 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 --> tests/ui/cast_lossless_bool.rs:9:13
| |
LL | let _ = true as u16; 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 --> tests/ui/cast_lossless_bool.rs:10:13
| |
LL | let _ = true as u32; 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 --> tests/ui/cast_lossless_bool.rs:11:13
| |
LL | let _ = true as u64; 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 --> tests/ui/cast_lossless_bool.rs:12:13
| |
LL | let _ = true as u128; 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 --> tests/ui/cast_lossless_bool.rs:13:13
| |
LL | let _ = true as usize; 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 --> tests/ui/cast_lossless_bool.rs:15:13
| |
LL | let _ = true as i8; 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 --> tests/ui/cast_lossless_bool.rs:16:13
| |
LL | let _ = true as i16; 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 --> tests/ui/cast_lossless_bool.rs:17:13
| |
LL | let _ = true as i32; 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 --> tests/ui/cast_lossless_bool.rs:18:13
| |
LL | let _ = true as i64; 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 --> tests/ui/cast_lossless_bool.rs:19:13
| |
LL | let _ = true as i128; 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 --> tests/ui/cast_lossless_bool.rs:20:13
| |
LL | let _ = true as isize; 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 --> tests/ui/cast_lossless_bool.rs:23:13
| |
LL | let _ = (true | false) as u16; 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 --> tests/ui/cast_lossless_bool.rs:25:13
| |
LL | let _ = true as U8; 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 --> tests/ui/cast_lossless_bool.rs:53:13
| |
LL | let _ = true as u8; 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 error: aborting due to 15 previous errors

View file

@ -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 --> tests/ui/cast_lossless_float.rs:12:13
| |
LL | let _ = x0 as f32; 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` = note: `-D clippy::cast-lossless` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` = 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 --> tests/ui/cast_lossless_float.rs:13:13
| |
LL | let _ = x0 as f64; 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 --> tests/ui/cast_lossless_float.rs:14:13
| |
LL | let _ = x0 as F32; 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 --> tests/ui/cast_lossless_float.rs:15:13
| |
LL | let _ = x0 as F64; 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 --> tests/ui/cast_lossless_float.rs:17:13
| |
LL | let _ = x1 as f32; 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 --> tests/ui/cast_lossless_float.rs:18:13
| |
LL | let _ = x1 as f64; 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 --> tests/ui/cast_lossless_float.rs:20:13
| |
LL | let _ = x2 as f32; 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 --> tests/ui/cast_lossless_float.rs:21:13
| |
LL | let _ = x2 as f64; 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 --> tests/ui/cast_lossless_float.rs:23:13
| |
LL | let _ = x3 as f32; 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 --> tests/ui/cast_lossless_float.rs:24:13
| |
LL | let _ = x3 as f64; 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 --> tests/ui/cast_lossless_float.rs:26:13
| |
LL | let _ = x4 as f64; 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 --> tests/ui/cast_lossless_float.rs:28:13
| |
LL | let _ = x5 as f64; 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 --> tests/ui/cast_lossless_float.rs:31:13
| |
LL | let _ = 1.0f32 as f64; 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 error: aborting due to 13 previous errors

View file

@ -1,39 +1,93 @@
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
#![warn(clippy::cast_lossless)] #![warn(clippy::cast_lossless)]
type I64 = i64; type I64Alias = i64;
type U128 = u128;
fn main() { fn main() {
// Test clippy::cast_lossless with casts to integer types // Test clippy::cast_lossless with casts to integer types
let _ = i16::from(1i8); u16::from(0u8);
let _ = i32::from(1i8); //~^ cast_lossless
let _ = i64::from(1i8); i16::from(0u8);
let _ = i16::from(1u8); //~^ cast_lossless
let _ = i32::from(1u8); u32::from(0u8);
let _ = i64::from(1u8); //~^ cast_lossless
let _ = u16::from(1u8); i32::from(0u8);
let _ = u32::from(1u8); //~^ cast_lossless
let _ = u64::from(1u8); u64::from(0u8);
let _ = i32::from(1i16); //~^ cast_lossless
let _ = i64::from(1i16); i64::from(0u8);
let _ = i32::from(1u16); //~^ cast_lossless
let _ = i64::from(1u16); u128::from(0u8);
let _ = u32::from(1u16); //~^ cast_lossless
let _ = u64::from(1u16); i128::from(0u8);
let _ = i64::from(1i32); //~^ cast_lossless
let _ = i64::from(1u32);
let _ = u64::from(1u32); 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 // Test with an expression wrapped in parens
let _ = u16::from(1u8 + 1u8); 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 let _: u16 = 0u8.into();
// see https://github.com/rust-lang/rust-clippy/issues/12492 //~^ cast_lossless
let _ = 1u8 as u128; let _: i16 = (-1i8).into();
let _ = 1u8 as U128; //~^ 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, // 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 x = 10_u128;
let _ = i32::from(sign_cast!(x, u8, i8)); let _ = i32::from(sign_cast!(x, u8, i8));
//~^ cast_lossless
let _ = i32::from(sign_cast!(x, u8, i8) + 1); 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 _ = <ty!()>::from(0u8);
}
const IN_CONST: u64 = 0u8 as u64;

View file

@ -1,39 +1,93 @@
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
#![warn(clippy::cast_lossless)] #![warn(clippy::cast_lossless)]
type I64 = i64; type I64Alias = i64;
type U128 = u128;
fn main() { fn main() {
// Test clippy::cast_lossless with casts to integer types // Test clippy::cast_lossless with casts to integer types
let _ = 1i8 as i16; 0u8 as u16;
let _ = 1i8 as i32; //~^ cast_lossless
let _ = 1i8 as i64; 0u8 as i16;
let _ = 1u8 as i16; //~^ cast_lossless
let _ = 1u8 as i32; 0u8 as u32;
let _ = 1u8 as i64; //~^ cast_lossless
let _ = 1u8 as u16; 0u8 as i32;
let _ = 1u8 as u32; //~^ cast_lossless
let _ = 1u8 as u64; 0u8 as u64;
let _ = 1i16 as i32; //~^ cast_lossless
let _ = 1i16 as i64; 0u8 as i64;
let _ = 1u16 as i32; //~^ cast_lossless
let _ = 1u16 as i64; 0u8 as u128;
let _ = 1u16 as u32; //~^ cast_lossless
let _ = 1u16 as u64; 0u8 as i128;
let _ = 1i32 as i64; //~^ cast_lossless
let _ = 1u32 as i64;
let _ = 1u32 as u64; 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 // Test with an expression wrapped in parens
let _ = (1u8 + 1u8) as u16; 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 let _: u16 = 0u8 as _;
// see https://github.com/rust-lang/rust-clippy/issues/12492 //~^ cast_lossless
let _ = 1u8 as u128; let _: i16 = -1i8 as _;
let _ = 1u8 as U128; //~^ 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, // 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 x = 10_u128;
let _ = sign_cast!(x, u8, i8) as i32; let _ = sign_cast!(x, u8, i8) as i32;
//~^ cast_lossless
let _ = (sign_cast!(x, u8, i8) + 1) as i32; 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;

View file

@ -1,137 +1,488 @@
error: casting `i8` to `i16` may become silently lossy if you later change the type error: casts from `u8` to `u16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:9:13 --> tests/ui/cast_lossless_integer.rs:8:5
| |
LL | let _ = 1i8 as i16; LL | 0u8 as u16;
| ^^^^^^^^^^ help: try: `i16::from(1i8)` | ^^^^^^^^^^
| |
= help: an `as` cast can become silently lossy if the types change in the future
= note: `-D clippy::cast-lossless` implied by `-D warnings` = note: `-D clippy::cast-lossless` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
help: use `u16::from` instead
error: casting `i8` to `i32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:10:13
| |
LL | let _ = 1i8 as i32; LL | u16::from(0u8);
| ^^^^^^^^^^ help: try: `i32::from(1i8)` | ~~~~~~~~~~~~~~
error: casting `i8` to `i64` may become silently lossy if you later change the type error: casts from `u8` to `i16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:11:13 --> tests/ui/cast_lossless_integer.rs:10:5
| |
LL | let _ = 1i8 as i64; LL | 0u8 as i16;
| ^^^^^^^^^^ 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 | let _ = 1u8 as i16; = help: an `as` cast can become silently lossy if the types change in the future
| ^^^^^^^^^^ help: try: `i16::from(1u8)` help: use `i16::from` instead
error: casting `u8` to `i32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:13:13
| |
LL | let _ = 1u8 as i32; LL | i16::from(0u8);
| ^^^^^^^^^^ help: try: `i32::from(1u8)` | ~~~~~~~~~~~~~~
error: casting `u8` to `i64` may become silently lossy if you later change the type error: casts from `u8` to `u32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:14:13 --> tests/ui/cast_lossless_integer.rs:12:5
| |
LL | let _ = 1u8 as i64; LL | 0u8 as u32;
| ^^^^^^^^^^ 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 | let _ = 1u8 as u16; = help: an `as` cast can become silently lossy if the types change in the future
| ^^^^^^^^^^ help: try: `u16::from(1u8)` help: use `u32::from` instead
error: casting `u8` to `u32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:16:13
| |
LL | let _ = 1u8 as u32; LL | u32::from(0u8);
| ^^^^^^^^^^ help: try: `u32::from(1u8)` | ~~~~~~~~~~~~~~
error: casting `u8` to `u64` may become silently lossy if you later change the type error: casts from `u8` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:17:13 --> tests/ui/cast_lossless_integer.rs:14:5
| |
LL | let _ = 1u8 as u64; LL | 0u8 as i32;
| ^^^^^^^^^^ 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 | let _ = 1i16 as i32; = help: an `as` cast can become silently lossy if the types change in the future
| ^^^^^^^^^^^ help: try: `i32::from(1i16)` help: use `i32::from` instead
error: casting `i16` to `i64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:19:13
| |
LL | let _ = 1i16 as i64; LL | i32::from(0u8);
| ^^^^^^^^^^^ help: try: `i64::from(1i16)` | ~~~~~~~~~~~~~~
error: casting `u16` to `i32` may become silently lossy if you later change the type error: casts from `u8` to `u64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:20:13 --> tests/ui/cast_lossless_integer.rs:16:5
| |
LL | let _ = 1u16 as i32; LL | 0u8 as u64;
| ^^^^^^^^^^^ 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 | let _ = 1u16 as i64; = help: an `as` cast can become silently lossy if the types change in the future
| ^^^^^^^^^^^ help: try: `i64::from(1u16)` help: use `u64::from` instead
error: casting `u16` to `u32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:22:13
| |
LL | let _ = 1u16 as u32; LL | u64::from(0u8);
| ^^^^^^^^^^^ help: try: `u32::from(1u16)` | ~~~~~~~~~~~~~~
error: casting `u16` to `u64` may become silently lossy if you later change the type error: casts from `u8` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:23:13 --> tests/ui/cast_lossless_integer.rs:18:5
| |
LL | let _ = 1u16 as u64; LL | 0u8 as i64;
| ^^^^^^^^^^^ 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 | let _ = 1i32 as i64; = help: an `as` cast can become silently lossy if the types change in the future
| ^^^^^^^^^^^ help: try: `i64::from(1i32)` help: use `i64::from` instead
error: casting `u32` to `i64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:25:13
| |
LL | let _ = 1u32 as i64; LL | i64::from(0u8);
| ^^^^^^^^^^^ help: try: `i64::from(1u32)` | ~~~~~~~~~~~~~~
error: casting `u32` to `u64` may become silently lossy if you later change the type error: casts from `u8` to `u128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:26:13 --> tests/ui/cast_lossless_integer.rs:20:5
| |
LL | let _ = 1u32 as u64; LL | 0u8 as u128;
| ^^^^^^^^^^^ help: try: `u64::from(1u32)` | ^^^^^^^^^^^
|
= 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 error: casts from `u8` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:29:13 --> 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; 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: an `as` cast can become silently lossy if the types change in the future
| ^^^^^^^^^^ help: try: `I64::from(1i8)` 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 error: casts from `i8` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:70:13 --> 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; 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 error: casts from `i8` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:71:13 --> tests/ui/cast_lossless_integer.rs:126:13
| |
LL | let _ = (sign_cast!(x, u8, i8) + 1) as i32; 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 `<ty!()>::from` instead
|
LL | let _ = <ty!()>::from(0u8);
| ~~~~~~~~~~~~~~~~~~
error: aborting due to 40 previous errors

View file

@ -25,6 +25,14 @@ fn main() {
let _ = 1.5_f64.sqrt(); let _ = 1.5_f64.sqrt();
let _ = 1.5_f64.powi(3); 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 // Cases where the lint shouldn't be applied
let _ = x.powf(2.1); let _ = x.powf(2.1);
let _ = x.powf(-2.1); let _ = x.powf(-2.1);

View file

@ -25,6 +25,14 @@ fn main() {
let _ = 1.5_f64.powf(1.0 / 2.0); let _ = 1.5_f64.powf(1.0 / 2.0);
let _ = 1.5_f64.powf(3.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 // Cases where the lint shouldn't be applied
let _ = x.powf(2.1); let _ = x.powf(2.1);
let _ = x.powf(-2.1); let _ = x.powf(-2.1);

View file

@ -119,76 +119,82 @@ LL | let _ = 1.5_f64.powf(3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.powi(3)` | ^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.powi(3)`
error: exponent for bases 2 and e can be computed more accurately 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); LL | let _ = 2f64.powf(x);
| ^^^^^^^^^^^^ help: consider using: `x.exp2()` | ^^^^^^^^^^^^ help: consider using: `x.exp2()`
error: exponent for bases 2 and e can be computed more accurately 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); LL | let _ = 2f64.powf(3.1);
| ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()` | ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()`
error: exponent for bases 2 and e can be computed more accurately 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); LL | let _ = 2f64.powf(-3.1);
| ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()` | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()`
error: exponent for bases 2 and e can be computed more accurately 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); LL | let _ = std::f64::consts::E.powf(x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
error: exponent for bases 2 and e can be computed more accurately 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); LL | let _ = std::f64::consts::E.powf(3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()`
error: exponent for bases 2 and e can be computed more accurately 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); LL | let _ = std::f64::consts::E.powf(-3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()`
error: square-root of a number can be computed more efficiently and accurately 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); LL | let _ = x.powf(1.0 / 2.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
error: cube-root of a number can be computed more accurately 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); LL | let _ = x.powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
error: exponentiation with integer powers can be computed more efficiently 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); LL | let _ = x.powf(3.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(3)` | ^^^^^^^^^^^ help: consider using: `x.powi(3)`
error: exponentiation with integer powers can be computed more efficiently 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); LL | let _ = x.powf(-2.0);
| ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
error: exponentiation with integer powers can be computed more efficiently 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); LL | let _ = x.powf(-2_147_483_648.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)`
error: exponentiation with integer powers can be computed more efficiently 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); LL | let _ = x.powf(2_147_483_647.0);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)` | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)`
error: aborting due to 31 previous errors error: aborting due to 32 previous errors

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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