Rollup merge of #89528 - FabianWolff:issue-89497, r=jackh726
Fix suggestion to borrow when casting from pointer to reference Fixes #89497.
This commit is contained in:
commit
f5bfa3450a
7 changed files with 80 additions and 14 deletions
|
@ -351,7 +351,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
);
|
);
|
||||||
let mut sugg = None;
|
let mut sugg = None;
|
||||||
let mut sugg_mutref = false;
|
let mut sugg_mutref = false;
|
||||||
if let ty::Ref(reg, _, mutbl) = *self.cast_ty.kind() {
|
if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
|
||||||
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() {
|
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() {
|
||||||
if fcx
|
if fcx
|
||||||
.try_coerce(
|
.try_coerce(
|
||||||
|
@ -366,7 +366,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
sugg = Some(format!("&{}*", mutbl.prefix_str()));
|
sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
|
||||||
}
|
}
|
||||||
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() {
|
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() {
|
||||||
if expr_mutbl == Mutability::Not
|
if expr_mutbl == Mutability::Not
|
||||||
|
@ -400,7 +400,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
sugg = Some(format!("&{}", mutbl.prefix_str()));
|
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
|
||||||
}
|
}
|
||||||
} else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() {
|
} else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() {
|
||||||
if fcx
|
if fcx
|
||||||
|
@ -416,19 +416,47 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
sugg = Some(format!("&{}", mutbl.prefix_str()));
|
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sugg_mutref {
|
if sugg_mutref {
|
||||||
err.span_label(self.span, "invalid cast");
|
err.span_label(self.span, "invalid cast");
|
||||||
err.span_note(self.expr.span, "this reference is immutable");
|
err.span_note(self.expr.span, "this reference is immutable");
|
||||||
err.span_note(self.cast_span, "trying to cast to a mutable reference type");
|
err.span_note(self.cast_span, "trying to cast to a mutable reference type");
|
||||||
} else if let Some(sugg) = sugg {
|
} else if let Some((sugg, remove_cast)) = sugg {
|
||||||
err.span_label(self.span, "invalid cast");
|
err.span_label(self.span, "invalid cast");
|
||||||
err.span_suggestion_verbose(
|
|
||||||
self.expr.span.shrink_to_lo(),
|
let has_parens = fcx
|
||||||
|
.tcx
|
||||||
|
.sess
|
||||||
|
.source_map()
|
||||||
|
.span_to_snippet(self.expr.span)
|
||||||
|
.map_or(false, |snip| snip.starts_with("("));
|
||||||
|
|
||||||
|
// Very crude check to see whether the expression must be wrapped
|
||||||
|
// in parentheses for the suggestion to work (issue #89497).
|
||||||
|
// Can/should be extended in the future.
|
||||||
|
let needs_parens = !has_parens
|
||||||
|
&& match self.expr.kind {
|
||||||
|
hir::ExprKind::Cast(..) => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)];
|
||||||
|
if needs_parens {
|
||||||
|
suggestion[0].1 += "(";
|
||||||
|
suggestion.push((self.expr.span.shrink_to_hi(), ")".to_string()));
|
||||||
|
}
|
||||||
|
if remove_cast {
|
||||||
|
suggestion.push((
|
||||||
|
self.expr.span.shrink_to_hi().to(self.cast_span),
|
||||||
|
String::new(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
err.multipart_suggestion_verbose(
|
||||||
"consider borrowing the value",
|
"consider borrowing the value",
|
||||||
sugg,
|
suggestion,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
} else if !matches!(
|
} else if !matches!(
|
||||||
|
|
10
src/test/ui/cast/issue-89497.fixed
Normal file
10
src/test/ui/cast/issue-89497.fixed
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Regression test for issue #89497.
|
||||||
|
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let pointer: usize = &1_i32 as *const i32 as usize;
|
||||||
|
let _reference: &'static i32 = unsafe { &*(pointer as *const i32) };
|
||||||
|
//~^ ERROR: non-primitive cast
|
||||||
|
//~| HELP: consider borrowing the value
|
||||||
|
}
|
10
src/test/ui/cast/issue-89497.rs
Normal file
10
src/test/ui/cast/issue-89497.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Regression test for issue #89497.
|
||||||
|
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let pointer: usize = &1_i32 as *const i32 as usize;
|
||||||
|
let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
|
||||||
|
//~^ ERROR: non-primitive cast
|
||||||
|
//~| HELP: consider borrowing the value
|
||||||
|
}
|
15
src/test/ui/cast/issue-89497.stderr
Normal file
15
src/test/ui/cast/issue-89497.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0605]: non-primitive cast: `*const i32` as `&'static i32`
|
||||||
|
--> $DIR/issue-89497.rs:7:45
|
||||||
|
|
|
||||||
|
LL | let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
|
||||||
|
|
|
||||||
|
help: consider borrowing the value
|
||||||
|
|
|
||||||
|
LL - let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
|
||||||
|
LL + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) };
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0605`.
|
|
@ -12,8 +12,9 @@ LL | v as &u8;
|
||||||
|
|
|
|
||||||
help: consider borrowing the value
|
help: consider borrowing the value
|
||||||
|
|
|
|
||||||
LL | &*v as &u8;
|
LL - v as &u8;
|
||||||
| ++
|
LL + &*v;
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,9 @@ LL | let _q: &isize = p as &isize;
|
||||||
|
|
|
|
||||||
help: consider borrowing the value
|
help: consider borrowing the value
|
||||||
|
|
|
|
||||||
LL | let _q: &isize = &*p as &isize;
|
LL - let _q: &isize = p as &isize;
|
||||||
| ++
|
LL + let _q: &isize = &*p;
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,9 @@ LL | let _ = v as &u8;
|
||||||
|
|
|
|
||||||
help: consider borrowing the value
|
help: consider borrowing the value
|
||||||
|
|
|
|
||||||
LL | let _ = &*v as &u8;
|
LL - let _ = v as &u8;
|
||||||
| ++
|
LL + let _ = &*v;
|
||||||
|
|
|
||||||
|
|
||||||
error[E0605]: non-primitive cast: `*const u8` as `E`
|
error[E0605]: non-primitive cast: `*const u8` as `E`
|
||||||
--> $DIR/cast-rfc0401.rs:30:13
|
--> $DIR/cast-rfc0401.rs:30:13
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue