Fix incorrect suggestions for E0605

This commit is contained in:
Fabian Wolff 2021-05-06 02:09:02 +02:00
parent bacf770f29
commit 71d1b2a009
7 changed files with 74 additions and 17 deletions

View file

@ -35,6 +35,7 @@ use crate::type_error_struct;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::Mutability;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::cast::{CastKind, CastTy};
use rustc_middle::ty::error::TypeError;
@ -347,15 +348,52 @@ impl<'a, 'tcx> CastCheck<'tcx> {
fcx.ty_to_string(self.cast_ty)
);
let mut sugg = None;
let mut sugg_mutref = false;
if let ty::Ref(reg, _, mutbl) = *self.cast_ty.kind() {
if fcx
.try_coerce(
self.expr,
fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
self.cast_ty,
AllowTwoPhase::No,
)
.is_ok()
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() {
if fcx
.try_coerce(
self.expr,
fcx.tcx.mk_ref(
&ty::RegionKind::ReErased,
TypeAndMut { ty: expr_ty, mutbl },
),
self.cast_ty,
AllowTwoPhase::No,
)
.is_ok()
{
sugg = Some(format!("&{}*", mutbl.prefix_str()));
}
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() {
if expr_mutbl == Mutability::Not
&& mutbl == Mutability::Mut
&& fcx
.try_coerce(
self.expr,
fcx.tcx.mk_ref(
expr_reg,
TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
),
self.cast_ty,
AllowTwoPhase::No,
)
.is_ok()
{
sugg_mutref = true;
}
}
if !sugg_mutref
&& sugg == None
&& fcx
.try_coerce(
self.expr,
fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
self.cast_ty,
AllowTwoPhase::No,
)
.is_ok()
{
sugg = Some(format!("&{}", mutbl.prefix_str()));
}
@ -375,11 +413,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
sugg = Some(format!("&{}", mutbl.prefix_str()));
}
}
if let Some(sugg) = sugg {
if sugg_mutref {
err.span_label(self.span, "invalid cast");
err.span_note(self.expr.span, "this reference is immutable");
err.span_note(self.cast_span, "trying to cast to a mutable reference type");
} else if let Some(sugg) = sugg {
err.span_label(self.span, "invalid cast");
err.span_suggestion_verbose(
self.expr.span.shrink_to_lo(),
"borrow the value for the cast to be valid",
"consider borrowing the value",
sugg,
Applicability::MachineApplicable,
);

View file

@ -4,7 +4,7 @@ error[E0605]: non-primitive cast: `Something` as `*const Something`
LL | let _pointer_to_something = something as *const Something;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
|
help: borrow the value for the cast to be valid
help: consider borrowing the value
|
LL | let _pointer_to_something = &something as *const Something;
| ^
@ -15,7 +15,7 @@ error[E0605]: non-primitive cast: `Something` as `*mut Something`
LL | let _mut_pointer_to_something = something as *mut Something;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
|
help: borrow the value for the cast to be valid
help: consider borrowing the value
|
LL | let _mut_pointer_to_something = &mut something as *mut Something;
| ^^^^

View file

@ -8,7 +8,12 @@ error[E0605]: non-primitive cast: `*const u8` as `&u8`
--> $DIR/E0605.rs:6:5
|
LL | v as &u8;
| ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
| ^^^^^^^^ invalid cast
|
help: consider borrowing the value
|
LL | &*v as &u8;
| ^^
error: aborting due to 2 previous errors

View file

@ -4,7 +4,7 @@ error[E0605]: non-primitive cast: `i32` as `&(dyn Any + 'static)`
LL | 0 as &dyn std::any::Any;
| ^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
|
help: borrow the value for the cast to be valid
help: consider borrowing the value
|
LL | &0 as &dyn std::any::Any;
| ^

View file

@ -4,7 +4,7 @@ error[E0605]: non-primitive cast: `Self` as `&dyn Index<usize, Output = <Self as
LL | let indexer = &(*self as &dyn Index<usize, Output = <Self as Index<usize>>::Output>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
|
help: borrow the value for the cast to be valid
help: consider borrowing the value
|
LL | let indexer = &(&*self as &dyn Index<usize, Output = <Self as Index<usize>>::Output>);
| ^

View file

@ -2,7 +2,12 @@ error[E0605]: non-primitive cast: `*const isize` as `&isize`
--> $DIR/issue-2995.rs:2:22
|
LL | let _q: &isize = p as &isize;
| ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
| ^^^^^^^^^^^ invalid cast
|
help: consider borrowing the value
|
LL | let _q: &isize = &*p as &isize;
| ^^
error: aborting due to previous error

View file

@ -24,7 +24,12 @@ error[E0605]: non-primitive cast: `*const u8` as `&u8`
--> $DIR/cast-rfc0401.rs:29:13
|
LL | let _ = v as &u8;
| ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
| ^^^^^^^^ invalid cast
|
help: consider borrowing the value
|
LL | let _ = &*v as &u8;
| ^^
error[E0605]: non-primitive cast: `*const u8` as `E`
--> $DIR/cast-rfc0401.rs:30:13