From ca1178f02237fd84649a30b74052da4ef265371f Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Mon, 16 Jan 2023 20:24:01 +1300 Subject: [PATCH 1/2] make `CastError::NeedsDeref` create a `MachineApplicable` suggestion + other misc fixes --- compiler/rustc_hir_typeck/src/cast.rs | 30 +++++++------------ tests/ui/error-codes/E0606.stderr | 10 ++++--- tests/ui/error-festival.stderr | 10 ++++--- tests/ui/mismatched_types/cast-rfc0401.stderr | 10 ++++--- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 0a230fca107af..b312a3d30af08 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -151,7 +151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[derive(Copy, Clone)] pub enum CastError { - ErrorGuaranteed, + ErrorGuaranteed(ErrorGuaranteed), CastToBool, CastToChar, @@ -176,8 +176,8 @@ pub enum CastError { } impl From for CastError { - fn from(_: ErrorGuaranteed) -> Self { - CastError::ErrorGuaranteed + fn from(err: ErrorGuaranteed) -> Self { + CastError::ErrorGuaranteed(err) } } @@ -225,11 +225,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) { match e { - CastError::ErrorGuaranteed => { + CastError::ErrorGuaranteed(_) => { // an error has already been reported } CastError::NeedDeref => { - let error_span = self.span; let mut err = make_invalid_casting_error( fcx.tcx.sess, self.span, @@ -237,21 +236,14 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.cast_ty, fcx, ); - let cast_ty = fcx.ty_to_string(self.cast_ty); - err.span_label( - error_span, - format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty), + + err.span_suggestion_verbose( + self.expr_span.shrink_to_lo(), + "dereference the expression", + "*", + Applicability::MachineApplicable, ); - if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr_span) { - err.span_suggestion( - self.expr_span, - "dereference the expression", - format!("*{}", snippet), - Applicability::MaybeIncorrect, - ); - } else { - err.span_help(self.expr_span, "dereference the expression with `*`"); - } + err.emit(); } CastError::NeedViaThinPtr | CastError::NeedViaPtr => { diff --git a/tests/ui/error-codes/E0606.stderr b/tests/ui/error-codes/E0606.stderr index fce24886eb0df..586b1f2fd5472 100644 --- a/tests/ui/error-codes/E0606.stderr +++ b/tests/ui/error-codes/E0606.stderr @@ -2,10 +2,12 @@ error[E0606]: casting `&u8` as `u8` is invalid --> $DIR/E0606.rs:2:5 | LL | &0u8 as u8; - | ----^^^^^^ - | | - | cannot cast `&u8` as `u8` - | help: dereference the expression: `*&0u8` + | ^^^^^^^^^^ + | +help: dereference the expression + | +LL | *&0u8 as u8; + | + error: aborting due to previous error diff --git a/tests/ui/error-festival.stderr b/tests/ui/error-festival.stderr index fe9956b70bdd7..e8ee1d96942f7 100644 --- a/tests/ui/error-festival.stderr +++ b/tests/ui/error-festival.stderr @@ -69,10 +69,12 @@ error[E0606]: casting `&u8` as `u32` is invalid --> $DIR/error-festival.rs:37:18 | LL | let y: u32 = x as u32; - | -^^^^^^^ - | | - | cannot cast `&u8` as `u32` - | help: dereference the expression: `*x` + | ^^^^^^^^ + | +help: dereference the expression + | +LL | let y: u32 = *x as u32; + | + error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` --> $DIR/error-festival.rs:41:5 diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr index eab8e8e80c424..2a36a352c7341 100644 --- a/tests/ui/mismatched_types/cast-rfc0401.stderr +++ b/tests/ui/mismatched_types/cast-rfc0401.stderr @@ -243,10 +243,12 @@ error[E0606]: casting `&{float}` as `f32` is invalid --> $DIR/cast-rfc0401.rs:71:30 | LL | vec![0.0].iter().map(|s| s as f32).collect::>(); - | -^^^^^^^ - | | - | cannot cast `&{float}` as `f32` - | help: dereference the expression: `*s` + | ^^^^^^^^ + | +help: dereference the expression + | +LL | vec![0.0].iter().map(|s| *s as f32).collect::>(); + | + error: aborting due to 34 previous errors From b73cdf1b29d25d3c6d0cc4f8a7744b08930e86ee Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Wed, 18 Jan 2023 13:14:56 +1300 Subject: [PATCH 2/2] special case removing `&` suggestion --- compiler/rustc_hir/src/hir.rs | 8 ++++++++ compiler/rustc_hir_typeck/src/cast.rs | 24 ++++++++++++++++++------ tests/ui/error-codes/E0606.rs | 3 ++- tests/ui/error-codes/E0606.stderr | 22 +++++++++++++++++----- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 60f5b79de1033..5e59475a7bdfc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1787,6 +1787,14 @@ impl Expr<'_> { expr } + pub fn peel_borrows(&self) -> &Self { + let mut expr = self; + while let ExprKind::AddrOf(.., inner) = &expr.kind { + expr = inner; + } + expr + } + pub fn can_have_side_effects(&self) -> bool { match self.peel_drop_temps().kind { ExprKind::Path(_) | ExprKind::Lit(_) => false, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index b312a3d30af08..712f9b87aed0a 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -31,6 +31,7 @@ use super::FnCtxt; use crate::type_error_struct; +use hir::ExprKind; use rustc_errors::{ struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, }; @@ -237,12 +238,23 @@ impl<'a, 'tcx> CastCheck<'tcx> { fcx, ); - err.span_suggestion_verbose( - self.expr_span.shrink_to_lo(), - "dereference the expression", - "*", - Applicability::MachineApplicable, - ); + if matches!(self.expr.kind, ExprKind::AddrOf(..)) { + // get just the borrow part of the expression + let span = self.expr_span.with_hi(self.expr.peel_borrows().span.lo()); + err.span_suggestion_verbose( + span, + "remove the unneeded borrow", + "", + Applicability::MachineApplicable, + ); + } else { + err.span_suggestion_verbose( + self.expr_span.shrink_to_lo(), + "dereference the expression", + "*", + Applicability::MachineApplicable, + ); + } err.emit(); } diff --git a/tests/ui/error-codes/E0606.rs b/tests/ui/error-codes/E0606.rs index cb0d8cfc31e23..6f6c6513846cf 100644 --- a/tests/ui/error-codes/E0606.rs +++ b/tests/ui/error-codes/E0606.rs @@ -1,3 +1,4 @@ fn main() { - &0u8 as u8; //~ ERROR E0606 + let x = &(&0u8 as u8); //~ ERROR E0606 + x as u8; //~ casting `&u8` as `u8` is invalid [E0606] } diff --git a/tests/ui/error-codes/E0606.stderr b/tests/ui/error-codes/E0606.stderr index 586b1f2fd5472..2492eb299cc55 100644 --- a/tests/ui/error-codes/E0606.stderr +++ b/tests/ui/error-codes/E0606.stderr @@ -1,14 +1,26 @@ error[E0606]: casting `&u8` as `u8` is invalid - --> $DIR/E0606.rs:2:5 + --> $DIR/E0606.rs:2:14 | -LL | &0u8 as u8; - | ^^^^^^^^^^ +LL | let x = &(&0u8 as u8); + | ^^^^^^^^^^^^ + | +help: remove the unneeded borrow + | +LL - let x = &(&0u8 as u8); +LL + let x = &(0u8 as u8); + | + +error[E0606]: casting `&u8` as `u8` is invalid + --> $DIR/E0606.rs:3:5 + | +LL | x as u8; + | ^^^^^^^ | help: dereference the expression | -LL | *&0u8 as u8; +LL | *x as u8; | + -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0606`.