Rollup merge of #106927 - Ezrashaw:e0606-make-machine-applicable, r=estebank
make `CastError::NeedsDeref` create a `MachineApplicable` suggestion Fixes #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.
This commit is contained in:
commit
1a878df2b8
6 changed files with 64 additions and 33 deletions
|
@ -1787,6 +1787,14 @@ impl Expr<'_> {
|
||||||
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 {
|
pub fn can_have_side_effects(&self) -> bool {
|
||||||
match self.peel_drop_temps().kind {
|
match self.peel_drop_temps().kind {
|
||||||
ExprKind::Path(_) | ExprKind::Lit(_) => false,
|
ExprKind::Path(_) | ExprKind::Lit(_) => false,
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
use super::FnCtxt;
|
use super::FnCtxt;
|
||||||
|
|
||||||
use crate::type_error_struct;
|
use crate::type_error_struct;
|
||||||
|
use hir::ExprKind;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
||||||
};
|
};
|
||||||
|
@ -151,7 +152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum CastError {
|
pub enum CastError {
|
||||||
ErrorGuaranteed,
|
ErrorGuaranteed(ErrorGuaranteed),
|
||||||
|
|
||||||
CastToBool,
|
CastToBool,
|
||||||
CastToChar,
|
CastToChar,
|
||||||
|
@ -176,8 +177,8 @@ pub enum CastError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ErrorGuaranteed> for CastError {
|
impl From<ErrorGuaranteed> for CastError {
|
||||||
fn from(_: ErrorGuaranteed) -> Self {
|
fn from(err: ErrorGuaranteed) -> Self {
|
||||||
CastError::ErrorGuaranteed
|
CastError::ErrorGuaranteed(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,11 +226,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
|
|
||||||
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
|
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
|
||||||
match e {
|
match e {
|
||||||
CastError::ErrorGuaranteed => {
|
CastError::ErrorGuaranteed(_) => {
|
||||||
// an error has already been reported
|
// an error has already been reported
|
||||||
}
|
}
|
||||||
CastError::NeedDeref => {
|
CastError::NeedDeref => {
|
||||||
let error_span = self.span;
|
|
||||||
let mut err = make_invalid_casting_error(
|
let mut err = make_invalid_casting_error(
|
||||||
fcx.tcx.sess,
|
fcx.tcx.sess,
|
||||||
self.span,
|
self.span,
|
||||||
|
@ -237,21 +237,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
self.cast_ty,
|
self.cast_ty,
|
||||||
fcx,
|
fcx,
|
||||||
);
|
);
|
||||||
let cast_ty = fcx.ty_to_string(self.cast_ty);
|
|
||||||
err.span_label(
|
if matches!(self.expr.kind, ExprKind::AddrOf(..)) {
|
||||||
error_span,
|
// get just the borrow part of the expression
|
||||||
format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty),
|
let span = self.expr_span.with_hi(self.expr.peel_borrows().span.lo());
|
||||||
);
|
err.span_suggestion_verbose(
|
||||||
if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr_span) {
|
span,
|
||||||
err.span_suggestion(
|
"remove the unneeded borrow",
|
||||||
self.expr_span,
|
"",
|
||||||
"dereference the expression",
|
Applicability::MachineApplicable,
|
||||||
format!("*{}", snippet),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
);
|
||||||
} else {
|
} 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();
|
err.emit();
|
||||||
}
|
}
|
||||||
CastError::NeedViaThinPtr | CastError::NeedViaPtr => {
|
CastError::NeedViaThinPtr | CastError::NeedViaPtr => {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
&0u8 as u8; //~ ERROR E0606
|
let x = &(&0u8 as u8); //~ ERROR E0606
|
||||||
|
x as u8; //~ casting `&u8` as `u8` is invalid [E0606]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,26 @@
|
||||||
error[E0606]: casting `&u8` as `u8` is invalid
|
error[E0606]: casting `&u8` as `u8` is invalid
|
||||||
--> $DIR/E0606.rs:2:5
|
--> $DIR/E0606.rs:2:14
|
||||||
|
|
|
||||||
|
LL | let x = &(&0u8 as u8);
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: remove the unneeded borrow
|
||||||
|
|
|
||||||
|
LL - let x = &(&0u8 as u8);
|
||||||
|
LL + let x = &(0u8 as u8);
|
||||||
|
|
|
|
||||||
LL | &0u8 as u8;
|
|
||||||
| ----^^^^^^
|
|
||||||
| |
|
|
||||||
| cannot cast `&u8` as `u8`
|
|
||||||
| help: dereference the expression: `*&0u8`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
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 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0606`.
|
For more information about this error, try `rustc --explain E0606`.
|
||||||
|
|
|
@ -69,10 +69,12 @@ error[E0606]: casting `&u8` as `u32` is invalid
|
||||||
--> $DIR/error-festival.rs:37:18
|
--> $DIR/error-festival.rs:37:18
|
||||||
|
|
|
|
||||||
LL | let y: u32 = x as u32;
|
LL | let y: u32 = x as u32;
|
||||||
| -^^^^^^^
|
| ^^^^^^^^
|
||||||
| |
|
|
|
||||||
| cannot cast `&u8` as `u32`
|
help: dereference the expression
|
||||||
| help: dereference the expression: `*x`
|
|
|
||||||
|
LL | let y: u32 = *x as u32;
|
||||||
|
| +
|
||||||
|
|
||||||
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
||||||
--> $DIR/error-festival.rs:41:5
|
--> $DIR/error-festival.rs:41:5
|
||||||
|
|
|
@ -243,10 +243,12 @@ error[E0606]: casting `&{float}` as `f32` is invalid
|
||||||
--> $DIR/cast-rfc0401.rs:71:30
|
--> $DIR/cast-rfc0401.rs:71:30
|
||||||
|
|
|
|
||||||
LL | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
|
LL | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
|
||||||
| -^^^^^^^
|
| ^^^^^^^^
|
||||||
| |
|
|
|
||||||
| cannot cast `&{float}` as `f32`
|
help: dereference the expression
|
||||||
| help: dereference the expression: `*s`
|
|
|
||||||
|
LL | vec![0.0].iter().map(|s| *s as f32).collect::<Vec<f32>>();
|
||||||
|
| +
|
||||||
|
|
||||||
error: aborting due to 34 previous errors
|
error: aborting due to 34 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue