Skip to content

Commit 1a878df

Browse files
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.
2 parents 30ddeef + b73cdf1 commit 1a878df

File tree

6 files changed

+64
-33
lines changed

6 files changed

+64
-33
lines changed

compiler/rustc_hir/src/hir.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,14 @@ impl Expr<'_> {
17871787
expr
17881788
}
17891789

1790+
pub fn peel_borrows(&self) -> &Self {
1791+
let mut expr = self;
1792+
while let ExprKind::AddrOf(.., inner) = &expr.kind {
1793+
expr = inner;
1794+
}
1795+
expr
1796+
}
1797+
17901798
pub fn can_have_side_effects(&self) -> bool {
17911799
match self.peel_drop_temps().kind {
17921800
ExprKind::Path(_) | ExprKind::Lit(_) => false,

compiler/rustc_hir_typeck/src/cast.rs

+21-17
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use super::FnCtxt;
3232

3333
use crate::type_error_struct;
34+
use hir::ExprKind;
3435
use rustc_errors::{
3536
struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
3637
};
@@ -151,7 +152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
151152

152153
#[derive(Copy, Clone)]
153154
pub enum CastError {
154-
ErrorGuaranteed,
155+
ErrorGuaranteed(ErrorGuaranteed),
155156

156157
CastToBool,
157158
CastToChar,
@@ -176,8 +177,8 @@ pub enum CastError {
176177
}
177178

178179
impl From<ErrorGuaranteed> for CastError {
179-
fn from(_: ErrorGuaranteed) -> Self {
180-
CastError::ErrorGuaranteed
180+
fn from(err: ErrorGuaranteed) -> Self {
181+
CastError::ErrorGuaranteed(err)
181182
}
182183
}
183184

@@ -225,33 +226,36 @@ impl<'a, 'tcx> CastCheck<'tcx> {
225226

226227
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
227228
match e {
228-
CastError::ErrorGuaranteed => {
229+
CastError::ErrorGuaranteed(_) => {
229230
// an error has already been reported
230231
}
231232
CastError::NeedDeref => {
232-
let error_span = self.span;
233233
let mut err = make_invalid_casting_error(
234234
fcx.tcx.sess,
235235
self.span,
236236
self.expr_ty,
237237
self.cast_ty,
238238
fcx,
239239
);
240-
let cast_ty = fcx.ty_to_string(self.cast_ty);
241-
err.span_label(
242-
error_span,
243-
format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty),
244-
);
245-
if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr_span) {
246-
err.span_suggestion(
247-
self.expr_span,
248-
"dereference the expression",
249-
format!("*{}", snippet),
250-
Applicability::MaybeIncorrect,
240+
241+
if matches!(self.expr.kind, ExprKind::AddrOf(..)) {
242+
// get just the borrow part of the expression
243+
let span = self.expr_span.with_hi(self.expr.peel_borrows().span.lo());
244+
err.span_suggestion_verbose(
245+
span,
246+
"remove the unneeded borrow",
247+
"",
248+
Applicability::MachineApplicable,
251249
);
252250
} else {
253-
err.span_help(self.expr_span, "dereference the expression with `*`");
251+
err.span_suggestion_verbose(
252+
self.expr_span.shrink_to_lo(),
253+
"dereference the expression",
254+
"*",
255+
Applicability::MachineApplicable,
256+
);
254257
}
258+
255259
err.emit();
256260
}
257261
CastError::NeedViaThinPtr | CastError::NeedViaPtr => {

tests/ui/error-codes/E0606.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
fn main() {
2-
&0u8 as u8; //~ ERROR E0606
2+
let x = &(&0u8 as u8); //~ ERROR E0606
3+
x as u8; //~ casting `&u8` as `u8` is invalid [E0606]
34
}

tests/ui/error-codes/E0606.stderr

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
error[E0606]: casting `&u8` as `u8` is invalid
2-
--> $DIR/E0606.rs:2:5
2+
--> $DIR/E0606.rs:2:14
33
|
4-
LL | &0u8 as u8;
5-
| ----^^^^^^
6-
| |
7-
| cannot cast `&u8` as `u8`
8-
| help: dereference the expression: `*&0u8`
4+
LL | let x = &(&0u8 as u8);
5+
| ^^^^^^^^^^^^
6+
|
7+
help: remove the unneeded borrow
8+
|
9+
LL - let x = &(&0u8 as u8);
10+
LL + let x = &(0u8 as u8);
11+
|
12+
13+
error[E0606]: casting `&u8` as `u8` is invalid
14+
--> $DIR/E0606.rs:3:5
15+
|
16+
LL | x as u8;
17+
| ^^^^^^^
18+
|
19+
help: dereference the expression
20+
|
21+
LL | *x as u8;
22+
| +
923

10-
error: aborting due to previous error
24+
error: aborting due to 2 previous errors
1125

1226
For more information about this error, try `rustc --explain E0606`.

tests/ui/error-festival.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@ error[E0606]: casting `&u8` as `u32` is invalid
6969
--> $DIR/error-festival.rs:37:18
7070
|
7171
LL | let y: u32 = x as u32;
72-
| -^^^^^^^
73-
| |
74-
| cannot cast `&u8` as `u32`
75-
| help: dereference the expression: `*x`
72+
| ^^^^^^^^
73+
|
74+
help: dereference the expression
75+
|
76+
LL | let y: u32 = *x as u32;
77+
| +
7678

7779
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
7880
--> $DIR/error-festival.rs:41:5

tests/ui/mismatched_types/cast-rfc0401.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,12 @@ error[E0606]: casting `&{float}` as `f32` is invalid
243243
--> $DIR/cast-rfc0401.rs:71:30
244244
|
245245
LL | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
246-
| -^^^^^^^
247-
| |
248-
| cannot cast `&{float}` as `f32`
249-
| help: dereference the expression: `*s`
246+
| ^^^^^^^^
247+
|
248+
help: dereference the expression
249+
|
250+
LL | vec![0.0].iter().map(|s| *s as f32).collect::<Vec<f32>>();
251+
| +
250252

251253
error: aborting due to 34 previous errors
252254

0 commit comments

Comments
 (0)