Skip to content

Commit

Permalink
Rollup merge of rust-lang#89528 - FabianWolff:issue-89497, r=jackh726
Browse files Browse the repository at this point in the history
Fix suggestion to borrow when casting from pointer to reference

Fixes rust-lang#89497.
  • Loading branch information
Manishearth committed Oct 6, 2021
2 parents 666f91b + 388bcc1 commit 8f1d942
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 14 deletions.
44 changes: 36 additions & 8 deletions compiler/rustc_typeck/src/check/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
);
let mut sugg = None;
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 fcx
.try_coerce(
Expand All @@ -366,7 +366,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
)
.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() {
if expr_mutbl == Mutability::Not
Expand Down Expand Up @@ -400,7 +400,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
)
.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() {
if fcx
Expand All @@ -416,19 +416,47 @@ impl<'a, 'tcx> CastCheck<'tcx> {
)
.is_ok()
{
sugg = Some(format!("&{}", mutbl.prefix_str()));
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
}
}
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 {
} else if let Some((sugg, remove_cast)) = sugg {
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",
sugg,
suggestion,
Applicability::MachineApplicable,
);
} else if !matches!(
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/cast/issue-89497.fixed
Original file line number Diff line number Diff line change
@@ -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 changes: 10 additions & 0 deletions src/test/ui/cast/issue-89497.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions src/test/ui/cast/issue-89497.stderr
Original file line number Diff line number Diff line change
@@ -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`.
5 changes: 3 additions & 2 deletions src/test/ui/error-codes/E0605.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ LL | v as &u8;
|
help: consider borrowing the value
|
LL | &*v as &u8;
| ++
LL - v as &u8;
LL + &*v;
|

error: aborting due to 2 previous errors

Expand Down
5 changes: 3 additions & 2 deletions src/test/ui/issues/issue-2995.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ LL | let _q: &isize = p as &isize;
|
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

Expand Down
5 changes: 3 additions & 2 deletions src/test/ui/mismatched_types/cast-rfc0401.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ LL | let _ = v as &u8;
|
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`
--> $DIR/cast-rfc0401.rs:30:13
Expand Down

0 comments on commit 8f1d942

Please sign in to comment.