diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 4be3ea890dc3a..921a5f5154a14 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -16,6 +16,21 @@ hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}` *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it } +hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool` + .suggestion = compare with zero instead + .help = compare with zero instead + .label = unsupported cast + +hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop` + +hir_typeck_cast_unknown_pointer = cannot cast {$to -> + [true] to + *[false] from + } a pointer of an unknown kind + .label_to = needs more type information + .note = the type information given here is insufficient to check whether the pointer cast is valid + .label_from = the type information given here is insufficient to check whether the pointer cast is valid + hir_typeck_const_select_must_be_const = this argument must be a `const fn` .help = consult the documentation on `const_eval_select` for more information @@ -29,6 +44,8 @@ hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to ` hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private +hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty` + hir_typeck_expected_default_return_type = expected `()` because of default return type hir_typeck_expected_return_type = expected `{$expected}` because of return type @@ -57,6 +74,13 @@ hir_typeck_functional_record_update_on_non_struct = hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml` hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc` +hir_typeck_int_to_fat = cannot cast `{$expr_ty}` to a pointer that {$known_wide -> + [true] is + *[false] may be + } wide +hir_typeck_int_to_fat_label = creating a `{$cast_ty}` requires both an address and {$metadata} +hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + hir_typeck_invalid_callee = expected function, found {$ty} hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` @@ -69,6 +93,16 @@ hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` la hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect .suggestion = change the type from `{$found_ty}` to `{$expected_ty}` +hir_typeck_lossy_provenance_int2ptr = + strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}` + .suggestion = use `.with_addr()` to adjust a valid pointer in the same allocation, to this address + .help = if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead + +hir_typeck_lossy_provenance_ptr2int = + under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}` + .suggestion = use `.addr()` to obtain the address of a pointer + .help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + hir_typeck_method_call_on_unknown_raw_pointee = cannot call a method on a raw pointer with an unknown pointee type @@ -113,8 +147,18 @@ hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling ` hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead +hir_typeck_trivial_cast = trivial {$numeric -> + [true] numeric cast + *[false] cast + }: `{$expr_ty}` as `{$cast_ty}` + .help = cast can be replaced by coercion; this might require a temporary variable + hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field + +hir_typeck_use_is_empty = + consider using the `is_empty` method on `{$expr_ty}` to determine if it contains anything + hir_typeck_yield_expr_outside_of_generator = yield expression outside of generator literal diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index e8d4e6b447f70..fa779701e61ed 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -30,11 +30,10 @@ use super::FnCtxt; +use crate::errors; use crate::type_error_struct; use hir::ExprKind; -use rustc_errors::{ - struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, -}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::mir::Mutability; @@ -321,33 +320,15 @@ impl<'a, 'tcx> CastCheck<'tcx> { .emit(); } CastError::CastToBool => { - let mut err = struct_span_err!( - fcx.tcx.sess, - self.span, - E0054, - "cannot cast `{}` as `bool`", - self.expr_ty - ); - - if self.expr_ty.is_numeric() { - match fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) { - Ok(snippet) => { - err.span_suggestion( - self.span, - "compare with zero instead", - format!("{snippet} != 0"), - Applicability::MachineApplicable, - ); - } - Err(_) => { - err.span_help(self.span, "compare with zero instead"); - } - } + let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let help = if self.expr_ty.is_numeric() { + errors::CannotCastToBoolHelp::Numeric( + self.expr_span.shrink_to_hi().with_hi(self.span.hi()), + ) } else { - err.span_label(self.span, "unsupported cast"); - } - - err.emit(); + errors::CannotCastToBoolHelp::Unsupported(self.span) + }; + fcx.tcx.sess.emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help }); } CastError::CastToChar => { let mut err = type_error_struct!( @@ -536,33 +517,20 @@ impl<'a, 'tcx> CastCheck<'tcx> { .emit(); } CastError::IntToFatCast(known_metadata) => { - let mut err = struct_span_err!( - fcx.tcx.sess, - self.cast_span, - E0606, - "cannot cast `{}` to a pointer that {} wide", - fcx.ty_to_string(self.expr_ty), - if known_metadata.is_some() { "is" } else { "may be" } - ); - - err.span_label( - self.cast_span, - format!( - "creating a `{}` requires both an address and {}", - self.cast_ty, - known_metadata.unwrap_or("type-specific metadata"), - ), - ); - - if fcx.tcx.sess.is_nightly_build() { - err.span_label( - self.expr_span, - "consider casting this expression to `*const ()`, \ - then using `core::ptr::from_raw_parts`", - ); - } - - err.emit(); + let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span); + let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); + let expr_ty = fcx.ty_to_string(self.expr_ty); + let metadata = known_metadata.unwrap_or("type-specific metadata"); + let known_wide = known_metadata.is_some(); + let span = self.cast_span; + fcx.tcx.sess.emit_err(errors::IntToWide { + span, + metadata, + expr_ty, + cast_ty, + expr_if_nightly, + known_wide, + }); } CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => { let unknown_cast_to = match e { @@ -570,27 +538,16 @@ impl<'a, 'tcx> CastCheck<'tcx> { CastError::UnknownExprPtrKind => false, _ => bug!(), }; - let mut err = struct_span_err!( - fcx.tcx.sess, - if unknown_cast_to { self.cast_span } else { self.span }, - E0641, - "cannot cast {} a pointer of an unknown kind", - if unknown_cast_to { "to" } else { "from" } - ); - if unknown_cast_to { - err.span_label(self.cast_span, "needs more type information"); - err.note( - "the type information given here is insufficient to check whether \ - the pointer cast is valid", - ); + let (span, sub) = if unknown_cast_to { + (self.cast_span, errors::CastUnknownPointerSub::To(self.cast_span)) } else { - err.span_label( - self.span, - "the type information given here is insufficient to check whether \ - the pointer cast is valid", - ); - } - err.emit(); + (self.cast_span, errors::CastUnknownPointerSub::From(self.span)) + }; + fcx.tcx.sess.emit_err(errors::CastUnknownPointer { + span, + to: unknown_cast_to, + sub, + }); } CastError::ForeignNonExhaustiveAdt => { make_invalid_casting_error( @@ -674,31 +631,18 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { - let t_cast = self.cast_ty; - let t_expr = self.expr_ty; - let (adjective, lint) = if t_cast.is_numeric() && t_expr.is_numeric() { - ("numeric ", lint::builtin::TRIVIAL_NUMERIC_CASTS) + let (numeric, lint) = if self.cast_ty.is_numeric() && self.expr_ty.is_numeric() { + (true, lint::builtin::TRIVIAL_NUMERIC_CASTS) } else { - ("", lint::builtin::TRIVIAL_CASTS) + (false, lint::builtin::TRIVIAL_CASTS) }; - fcx.tcx.struct_span_lint_hir( + let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); + fcx.tcx.emit_spanned_lint( lint, self.expr.hir_id, self.span, - DelayDm(|| { - format!( - "trivial {}cast: `{}` as `{}`", - adjective, - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast) - ) - }), - |lint| { - lint.help( - "cast can be replaced by coercion; this might \ - require a temporary variable", - ) - }, + errors::TrivialCast { numeric, expr_ty, cast_ty }, ); } @@ -991,93 +935,67 @@ impl<'a, 'tcx> CastCheck<'tcx> { if let ty::Adt(d, _) = self.expr_ty.kind() && d.has_dtor(fcx.tcx) { - fcx.tcx.struct_span_lint_hir( + let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); + + fcx.tcx.emit_spanned_lint( lint::builtin::CENUM_IMPL_DROP_CAST, self.expr.hir_id, self.span, - DelayDm(|| format!( - "cannot cast enum `{}` into integer `{}` because it implements `Drop`", - self.expr_ty, self.cast_ty - )), - |lint| { - lint - }, + errors::CastEnumDrop { + expr_ty, + cast_ty, + } ); } } fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { - fcx.tcx.struct_span_lint_hir( + let expr_prec = self.expr.precedence().order(); + let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX; + + let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize)); + let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span); + let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); + let expr_span = self.expr_span.shrink_to_lo(); + let sugg = match (needs_parens, needs_cast) { + (true, true) => errors::LossyProvenancePtr2IntSuggestion::NeedsParensCast { + expr_span, + cast_span, + cast_ty, + }, + (true, false) => { + errors::LossyProvenancePtr2IntSuggestion::NeedsParens { expr_span, cast_span } + } + (false, true) => { + errors::LossyProvenancePtr2IntSuggestion::NeedsCast { cast_span, cast_ty } + } + (false, false) => errors::LossyProvenancePtr2IntSuggestion::Other { cast_span }, + }; + + let lint = errors::LossyProvenancePtr2Int { expr_ty, cast_ty, sugg }; + fcx.tcx.emit_spanned_lint( lint::builtin::LOSSY_PROVENANCE_CASTS, self.expr.hir_id, self.span, - DelayDm(|| format!( - "under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`", - self.expr_ty, self.cast_ty - )), - |lint| { - let msg = "use `.addr()` to obtain the address of a pointer"; - - let expr_prec = self.expr.precedence().order(); - let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX; - - let scalar_cast = match t_c { - ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(), - _ => format!(" as {}", self.cast_ty), - }; - - let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span); - - if needs_parens { - let suggestions = vec![ - (self.expr_span.shrink_to_lo(), String::from("(")), - (cast_span, format!(").addr(){scalar_cast}")), - ]; - - lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect); - } else { - lint.span_suggestion( - cast_span, - msg, - format!(".addr(){scalar_cast}"), - Applicability::MaybeIncorrect, - ); - } - - lint.help( - "if you can't comply with strict provenance and need to expose the pointer \ - provenance you can use `.expose_addr()` instead" - ); - - lint - }, + lint, ); } fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { - fcx.tcx.struct_span_lint_hir( + let sugg = errors::LossyProvenanceInt2PtrSuggestion { + lo: self.expr_span.shrink_to_lo(), + hi: self.expr_span.shrink_to_hi().to(self.cast_span), + }; + let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); + let lint = errors::LossyProvenanceInt2Ptr { expr_ty, cast_ty, sugg }; + fcx.tcx.emit_spanned_lint( lint::builtin::FUZZY_PROVENANCE_CASTS, self.expr.hir_id, self.span, - DelayDm(|| format!( - "strict provenance disallows casting integer `{}` to pointer `{}`", - self.expr_ty, self.cast_ty - )), - |lint| { - let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address"; - let suggestions = vec![ - (self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")), - (self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")), - ]; - - lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect); - lint.help( - "if you can't comply with strict provenance and don't have a pointer with \ - the correct provenance you can use `std::ptr::from_exposed_addr()` instead" - ); - - lint - }, + lint, ); } @@ -1093,26 +1011,19 @@ impl<'a, 'tcx> CastCheck<'tcx> { if let Some((deref_ty, _)) = derefed { // Give a note about what the expr derefs to. if deref_ty != self.expr_ty.peel_refs() { - err.span_note( - self.expr_span, - format!( - "this expression `Deref`s to `{}` which implements `is_empty`", - fcx.ty_to_string(deref_ty) - ), - ); + err.subdiagnostic(errors::DerefImplsIsEmpty { + span: self.expr_span, + deref_ty: fcx.ty_to_string(deref_ty), + }); } // Create a multipart suggestion: add `!` and `.is_empty()` in // place of the cast. - let suggestion = vec![ - (self.expr_span.shrink_to_lo(), "!".to_string()), - (self.span.with_lo(self.expr_span.hi()), ".is_empty()".to_string()), - ]; - - err.multipart_suggestion_verbose(format!( - "consider using the `is_empty` method on `{}` to determine if it contains anything", - fcx.ty_to_string(self.expr_ty), - ), suggestion, Applicability::MaybeIncorrect); + err.subdiagnostic(errors::UseIsEmpty { + lo: self.expr_span.shrink_to_lo(), + hi: self.span.with_lo(self.expr_span.hi()), + expr_ty: fcx.ty_to_string(self.expr_ty), + }); } } } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index c1d7056b1a020..7152585d44087 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -6,7 +6,7 @@ use rustc_errors::{ AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage, }; -use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{ edition::{Edition, LATEST_STABLE_EDITION}, @@ -269,6 +269,69 @@ pub struct LangStartIncorrectRetTy<'tcx> { pub found_ty: Ty<'tcx>, } +#[derive(LintDiagnostic)] +#[diag(hir_typeck_lossy_provenance_int2ptr)] +#[help] +pub struct LossyProvenanceInt2Ptr<'tcx> { + pub expr_ty: Ty<'tcx>, + pub cast_ty: Ty<'tcx>, + #[subdiagnostic] + pub sugg: LossyProvenanceInt2PtrSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(hir_typeck_suggestion, applicability = "has-placeholders")] +pub struct LossyProvenanceInt2PtrSuggestion { + #[suggestion_part(code = "(...).with_addr(")] + pub lo: Span, + #[suggestion_part(code = ")")] + pub hi: Span, +} + +#[derive(LintDiagnostic)] +#[diag(hir_typeck_lossy_provenance_ptr2int)] +#[help] +pub struct LossyProvenancePtr2Int<'tcx> { + pub expr_ty: Ty<'tcx>, + pub cast_ty: Ty<'tcx>, + #[subdiagnostic] + pub sugg: LossyProvenancePtr2IntSuggestion<'tcx>, +} + +#[derive(Subdiagnostic)] +pub enum LossyProvenancePtr2IntSuggestion<'tcx> { + #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")] + NeedsParensCast { + #[suggestion_part(code = "(")] + expr_span: Span, + #[suggestion_part(code = ").addr() as {cast_ty}")] + cast_span: Span, + cast_ty: Ty<'tcx>, + }, + #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")] + NeedsParens { + #[suggestion_part(code = "(")] + expr_span: Span, + #[suggestion_part(code = ").addr()")] + cast_span: Span, + }, + #[suggestion( + hir_typeck_suggestion, + code = ".addr() as {cast_ty}", + applicability = "maybe-incorrect" + )] + NeedsCast { + #[primary_span] + cast_span: Span, + cast_ty: Ty<'tcx>, + }, + #[suggestion(hir_typeck_suggestion, code = ".addr()", applicability = "maybe-incorrect")] + Other { + #[primary_span] + cast_span: Span, + }, +} + #[derive(Subdiagnostic)] pub enum HelpUseLatestEdition { #[help(hir_typeck_help_set_edition_cargo)] @@ -298,6 +361,20 @@ pub struct InvalidCallee { pub ty: String, } +#[derive(Diagnostic)] +#[diag(hir_typeck_int_to_fat, code = "E0606")] +pub struct IntToWide<'tcx> { + #[primary_span] + #[label(hir_typeck_int_to_fat_label)] + pub span: Span, + pub metadata: &'tcx str, + pub expr_ty: String, + pub cast_ty: Ty<'tcx>, + #[label(hir_typeck_int_to_fat_label_nightly)] + pub expr_if_nightly: Option, + pub known_wide: bool, +} + #[derive(Subdiagnostic)] pub enum OptionResultRefMismatch { #[suggestion( @@ -396,6 +473,20 @@ pub struct UnionPatDotDot { pub span: Span, } +#[derive(Subdiagnostic)] +#[multipart_suggestion( + hir_typeck_use_is_empty, + applicability = "maybe-incorrect", + style = "verbose" +)] +pub struct UseIsEmpty { + #[suggestion_part(code = "!")] + pub lo: Span, + #[suggestion_part(code = ".is_empty()")] + pub hi: Span, + pub expr_ty: String, +} + #[derive(Diagnostic)] #[diag(hir_typeck_arg_mismatch_indeterminate)] pub struct ArgMismatchIndeterminate { @@ -442,6 +533,15 @@ pub struct SuggestPtrNullMut { pub span: Span, } +#[derive(LintDiagnostic)] +#[diag(hir_typeck_trivial_cast)] +#[help] +pub struct TrivialCast<'tcx> { + pub numeric: bool, + pub expr_ty: Ty<'tcx>, + pub cast_ty: Ty<'tcx>, +} + #[derive(Diagnostic)] #[diag(hir_typeck_no_associated_item, code = "E0599")] pub struct NoAssociatedItem { @@ -464,6 +564,74 @@ pub struct CandidateTraitNote { pub action_or_ty: String, } +#[derive(Diagnostic)] +#[diag(hir_typeck_cannot_cast_to_bool, code = "E0054")] +pub struct CannotCastToBool<'tcx> { + #[primary_span] + pub span: Span, + pub expr_ty: Ty<'tcx>, + #[subdiagnostic] + pub help: CannotCastToBoolHelp, +} + +#[derive(LintDiagnostic)] +#[diag(hir_typeck_cast_enum_drop)] +pub struct CastEnumDrop<'tcx> { + pub expr_ty: Ty<'tcx>, + pub cast_ty: Ty<'tcx>, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_cast_unknown_pointer, code = "E0641")] +pub struct CastUnknownPointer { + #[primary_span] + pub span: Span, + pub to: bool, + #[subdiagnostic] + pub sub: CastUnknownPointerSub, +} + +pub enum CastUnknownPointerSub { + To(Span), + From(Span), +} + +impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, f: F) + where + F: Fn( + &mut Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + match self { + CastUnknownPointerSub::To(span) => { + let msg = f(diag, crate::fluent_generated::hir_typeck_label_to.into()); + diag.span_label(span, msg); + let msg = f(diag, crate::fluent_generated::hir_typeck_note.into()); + diag.note(msg); + } + CastUnknownPointerSub::From(span) => { + let msg = f(diag, crate::fluent_generated::hir_typeck_label_from.into()); + diag.span_label(span, msg); + } + } + } +} + +#[derive(Subdiagnostic)] +pub enum CannotCastToBoolHelp { + #[suggestion( + hir_typeck_suggestion, + applicability = "machine-applicable", + code = " != 0", + style = "verbose" + )] + Numeric(#[primary_span] Span), + #[label(hir_typeck_label)] + Unsupported(#[primary_span] Span), +} + #[derive(Diagnostic)] #[diag(hir_typeck_ctor_is_private, code = "E0603")] pub struct CtorIsPrivate { @@ -472,6 +640,14 @@ pub struct CtorIsPrivate { pub def: String, } +#[derive(Subdiagnostic)] +#[note(hir_typeck_deref_is_empty)] +pub struct DerefImplsIsEmpty { + #[primary_span] + pub span: Span, + pub deref_ty: String, +} + #[derive(Subdiagnostic)] #[multipart_suggestion( hir_typeck_convert_using_method, diff --git a/tests/ui/cast/cast-as-bool.rs b/tests/ui/cast/cast-as-bool.rs index 750a88f97ebed..511a02718fe21 100644 --- a/tests/ui/cast/cast-as-bool.rs +++ b/tests/ui/cast/cast-as-bool.rs @@ -1,11 +1,11 @@ fn main() { let u = 5 as bool; //~ ERROR cannot cast `i32` as `bool` //~| HELP compare with zero instead - //~| SUGGESTION 5 != 0 + //~| SUGGESTION != 0 let t = (1 + 2) as bool; //~ ERROR cannot cast `i32` as `bool` //~| HELP compare with zero instead - //~| SUGGESTION (1 + 2) != 0 + //~| SUGGESTION != 0 let _ = 5_u32 as bool; //~ ERROR cannot cast `u32` as `bool` //~| HELP compare with zero instead diff --git a/tests/ui/cast/cast-as-bool.stderr b/tests/ui/cast/cast-as-bool.stderr index 852fb30cc202f..4ff56a95e49a3 100644 --- a/tests/ui/cast/cast-as-bool.stderr +++ b/tests/ui/cast/cast-as-bool.stderr @@ -2,25 +2,45 @@ error[E0054]: cannot cast `i32` as `bool` --> $DIR/cast-as-bool.rs:2:13 | LL | let u = 5 as bool; - | ^^^^^^^^^ help: compare with zero instead: `5 != 0` + | ^^^^^^^^^ + | +help: compare with zero instead + | +LL | let u = 5 != 0; + | ~~~~ error[E0054]: cannot cast `i32` as `bool` --> $DIR/cast-as-bool.rs:6:13 | LL | let t = (1 + 2) as bool; - | ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0` + | ^^^^^^^^^^^^^^^ + | +help: compare with zero instead + | +LL | let t = (1 + 2) != 0; + | ~~~~ error[E0054]: cannot cast `u32` as `bool` --> $DIR/cast-as-bool.rs:10:13 | LL | let _ = 5_u32 as bool; - | ^^^^^^^^^^^^^ help: compare with zero instead: `5_u32 != 0` + | ^^^^^^^^^^^^^ + | +help: compare with zero instead + | +LL | let _ = 5_u32 != 0; + | ~~~~ error[E0054]: cannot cast `f64` as `bool` --> $DIR/cast-as-bool.rs:13:13 | LL | let _ = 64.0_f64 as bool; - | ^^^^^^^^^^^^^^^^ help: compare with zero instead: `64.0_f64 != 0` + | ^^^^^^^^^^^^^^^^ + | +help: compare with zero instead + | +LL | let _ = 64.0_f64 != 0; + | ~~~~ error[E0054]: cannot cast `IntEnum` as `bool` --> $DIR/cast-as-bool.rs:24:13 diff --git a/tests/ui/cast/cast-rfc0401-2.stderr b/tests/ui/cast/cast-rfc0401-2.stderr index 5dc21ca847c93..dd90c3a97231a 100644 --- a/tests/ui/cast/cast-rfc0401-2.stderr +++ b/tests/ui/cast/cast-rfc0401-2.stderr @@ -2,7 +2,12 @@ error[E0054]: cannot cast `i32` as `bool` --> $DIR/cast-rfc0401-2.rs:6:13 | LL | let _ = 3 as bool; - | ^^^^^^^^^ help: compare with zero instead: `3 != 0` + | ^^^^^^^^^ + | +help: compare with zero instead + | +LL | let _ = 3 != 0; + | ~~~~ error: aborting due to previous error diff --git a/tests/ui/error-codes/E0054.stderr b/tests/ui/error-codes/E0054.stderr index ea81f4476a7da..0a4adabbaf6dc 100644 --- a/tests/ui/error-codes/E0054.stderr +++ b/tests/ui/error-codes/E0054.stderr @@ -2,7 +2,12 @@ error[E0054]: cannot cast `i32` as `bool` --> $DIR/E0054.rs:3:24 | LL | let x_is_nonzero = x as bool; - | ^^^^^^^^^ help: compare with zero instead: `x != 0` + | ^^^^^^^^^ + | +help: compare with zero instead + | +LL | let x_is_nonzero = x != 0; + | ~~~~ error: aborting due to previous error diff --git a/tests/ui/error-festival.stderr b/tests/ui/error-festival.stderr index 74a2bc8d7682e..9d75671c4e6b4 100644 --- a/tests/ui/error-festival.stderr +++ b/tests/ui/error-festival.stderr @@ -63,7 +63,12 @@ error[E0054]: cannot cast `{integer}` as `bool` --> $DIR/error-festival.rs:33:24 | LL | let x_is_nonzero = x as bool; - | ^^^^^^^^^ help: compare with zero instead: `x != 0` + | ^^^^^^^^^ + | +help: compare with zero instead + | +LL | let x_is_nonzero = x != 0; + | ~~~~ error[E0606]: casting `&u8` as `u32` is invalid --> $DIR/error-festival.rs:37:18 diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr index 0cea60746bfe3..d63cec489176b 100644 --- a/tests/ui/mismatched_types/cast-rfc0401.stderr +++ b/tests/ui/mismatched_types/cast-rfc0401.stderr @@ -86,7 +86,12 @@ error[E0054]: cannot cast `i32` as `bool` --> $DIR/cast-rfc0401.rs:39:13 | LL | let _ = 3_i32 as bool; - | ^^^^^^^^^^^^^ help: compare with zero instead: `3_i32 != 0` + | ^^^^^^^^^^^^^ + | +help: compare with zero instead + | +LL | let _ = 3_i32 != 0; + | ~~~~ error[E0054]: cannot cast `E` as `bool` --> $DIR/cast-rfc0401.rs:40:13