Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 71d1b2a

Browse files
committed
Fix incorrect suggestions for E0605
1 parent bacf770 commit 71d1b2a

File tree

7 files changed

+74
-17
lines changed

7 files changed

+74
-17
lines changed

compiler/rustc_typeck/src/check/cast.rs

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::type_error_struct;
3535
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
3636
use rustc_hir as hir;
3737
use rustc_hir::lang_items::LangItem;
38+
use rustc_middle::mir::Mutability;
3839
use rustc_middle::ty::adjustment::AllowTwoPhase;
3940
use rustc_middle::ty::cast::{CastKind, CastTy};
4041
use rustc_middle::ty::error::TypeError;
@@ -347,15 +348,52 @@ impl<'a, 'tcx> CastCheck<'tcx> {
347348
fcx.ty_to_string(self.cast_ty)
348349
);
349350
let mut sugg = None;
351+
let mut sugg_mutref = false;
350352
if let ty::Ref(reg, _, mutbl) = *self.cast_ty.kind() {
351-
if fcx
352-
.try_coerce(
353-
self.expr,
354-
fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
355-
self.cast_ty,
356-
AllowTwoPhase::No,
357-
)
358-
.is_ok()
353+
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() {
354+
if fcx
355+
.try_coerce(
356+
self.expr,
357+
fcx.tcx.mk_ref(
358+
&ty::RegionKind::ReErased,
359+
TypeAndMut { ty: expr_ty, mutbl },
360+
),
361+
self.cast_ty,
362+
AllowTwoPhase::No,
363+
)
364+
.is_ok()
365+
{
366+
sugg = Some(format!("&{}*", mutbl.prefix_str()));
367+
}
368+
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() {
369+
if expr_mutbl == Mutability::Not
370+
&& mutbl == Mutability::Mut
371+
&& fcx
372+
.try_coerce(
373+
self.expr,
374+
fcx.tcx.mk_ref(
375+
expr_reg,
376+
TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
377+
),
378+
self.cast_ty,
379+
AllowTwoPhase::No,
380+
)
381+
.is_ok()
382+
{
383+
sugg_mutref = true;
384+
}
385+
}
386+
387+
if !sugg_mutref
388+
&& sugg == None
389+
&& fcx
390+
.try_coerce(
391+
self.expr,
392+
fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
393+
self.cast_ty,
394+
AllowTwoPhase::No,
395+
)
396+
.is_ok()
359397
{
360398
sugg = Some(format!("&{}", mutbl.prefix_str()));
361399
}
@@ -375,11 +413,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
375413
sugg = Some(format!("&{}", mutbl.prefix_str()));
376414
}
377415
}
378-
if let Some(sugg) = sugg {
416+
if sugg_mutref {
417+
err.span_label(self.span, "invalid cast");
418+
err.span_note(self.expr.span, "this reference is immutable");
419+
err.span_note(self.cast_span, "trying to cast to a mutable reference type");
420+
} else if let Some(sugg) = sugg {
379421
err.span_label(self.span, "invalid cast");
380422
err.span_suggestion_verbose(
381423
self.expr.span.shrink_to_lo(),
382-
"borrow the value for the cast to be valid",
424+
"consider borrowing the value",
383425
sugg,
384426
Applicability::MachineApplicable,
385427
);

src/test/ui/cast/issue-84213.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0605]: non-primitive cast: `Something` as `*const Something`
44
LL | let _pointer_to_something = something as *const Something;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
66
|
7-
help: borrow the value for the cast to be valid
7+
help: consider borrowing the value
88
|
99
LL | let _pointer_to_something = &something as *const Something;
1010
| ^
@@ -15,7 +15,7 @@ error[E0605]: non-primitive cast: `Something` as `*mut Something`
1515
LL | let _mut_pointer_to_something = something as *mut Something;
1616
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
1717
|
18-
help: borrow the value for the cast to be valid
18+
help: consider borrowing the value
1919
|
2020
LL | let _mut_pointer_to_something = &mut something as *mut Something;
2121
| ^^^^

src/test/ui/error-codes/E0605.stderr

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ error[E0605]: non-primitive cast: `*const u8` as `&u8`
88
--> $DIR/E0605.rs:6:5
99
|
1010
LL | v as &u8;
11-
| ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
11+
| ^^^^^^^^ invalid cast
12+
|
13+
help: consider borrowing the value
14+
|
15+
LL | &*v as &u8;
16+
| ^^
1217

1318
error: aborting due to 2 previous errors
1419

src/test/ui/issues/issue-22289.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0605]: non-primitive cast: `i32` as `&(dyn Any + 'static)`
44
LL | 0 as &dyn std::any::Any;
55
| ^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
66
|
7-
help: borrow the value for the cast to be valid
7+
help: consider borrowing the value
88
|
99
LL | &0 as &dyn std::any::Any;
1010
| ^

src/test/ui/issues/issue-22312.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0605]: non-primitive cast: `Self` as `&dyn Index<usize, Output = <Self as
44
LL | let indexer = &(*self as &dyn Index<usize, Output = <Self as Index<usize>>::Output>);
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
66
|
7-
help: borrow the value for the cast to be valid
7+
help: consider borrowing the value
88
|
99
LL | let indexer = &(&*self as &dyn Index<usize, Output = <Self as Index<usize>>::Output>);
1010
| ^

src/test/ui/issues/issue-2995.stderr

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ error[E0605]: non-primitive cast: `*const isize` as `&isize`
22
--> $DIR/issue-2995.rs:2:22
33
|
44
LL | let _q: &isize = p as &isize;
5-
| ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
5+
| ^^^^^^^^^^^ invalid cast
6+
|
7+
help: consider borrowing the value
8+
|
9+
LL | let _q: &isize = &*p as &isize;
10+
| ^^
611

712
error: aborting due to previous error
813

src/test/ui/mismatched_types/cast-rfc0401.stderr

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ error[E0605]: non-primitive cast: `*const u8` as `&u8`
2424
--> $DIR/cast-rfc0401.rs:29:13
2525
|
2626
LL | let _ = v as &u8;
27-
| ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
27+
| ^^^^^^^^ invalid cast
28+
|
29+
help: consider borrowing the value
30+
|
31+
LL | let _ = &*v as &u8;
32+
| ^^
2833

2934
error[E0605]: non-primitive cast: `*const u8` as `E`
3035
--> $DIR/cast-rfc0401.rs:30:13

0 commit comments

Comments
 (0)