Skip to content

Commit

Permalink
Rollup merge of rust-lang#106927 - Ezrashaw:e0606-make-machine-applic…
Browse files Browse the repository at this point in the history
…able, r=estebank

make `CastError::NeedsDeref` create a `MachineApplicable` suggestion

Fixes rust-lang#106903

Simple impl for the linked issue. I also made some other small changes:
- `CastError::ErrorGuaranteed` now owns an actual `ErrorGuaranteed`. This better enforces the static guarantees of `ErrorGuaranteed`.
- `CastError::NeedDeref` code simplified a bit, we now just suggest the `*`, instead of the whole expression as well.
  • Loading branch information
GuillaumeGomez authored Jan 19, 2023
2 parents 30ddeef + b73cdf1 commit 1a878df
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 33 deletions.
8 changes: 8 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
38 changes: 21 additions & 17 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -151,7 +152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

#[derive(Copy, Clone)]
pub enum CastError {
ErrorGuaranteed,
ErrorGuaranteed(ErrorGuaranteed),

CastToBool,
CastToChar,
Expand All @@ -176,8 +177,8 @@ pub enum CastError {
}

impl From<ErrorGuaranteed> for CastError {
fn from(_: ErrorGuaranteed) -> Self {
CastError::ErrorGuaranteed
fn from(err: ErrorGuaranteed) -> Self {
CastError::ErrorGuaranteed(err)
}
}

Expand Down Expand Up @@ -225,33 +226,36 @@ 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,
self.expr_ty,
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),
);
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,

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_help(self.expr_span, "dereference the expression with `*`");
err.span_suggestion_verbose(
self.expr_span.shrink_to_lo(),
"dereference the expression",
"*",
Applicability::MachineApplicable,
);
}

err.emit();
}
CastError::NeedViaThinPtr | CastError::NeedViaPtr => {
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/error-codes/E0606.rs
Original file line number Diff line number Diff line change
@@ -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]
}
28 changes: 21 additions & 7 deletions tests/ui/error-codes/E0606.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
error[E0606]: casting `&u8` as `u8` is invalid
--> $DIR/E0606.rs:2:5
--> $DIR/E0606.rs:2:14
|
LL | &0u8 as u8;
| ----^^^^^^
| |
| cannot cast `&u8` as `u8`
| help: dereference the expression: `*&0u8`
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 | *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`.
10 changes: 6 additions & 4 deletions tests/ui/error-festival.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions tests/ui/mismatched_types/cast-rfc0401.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<f32>>();
| -^^^^^^^
| |
| 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::<Vec<f32>>();
| +

error: aborting due to 34 previous errors

Expand Down

0 comments on commit 1a878df

Please sign in to comment.