Skip to content

Commit f5bfa34

Browse files
authored
Rollup merge of #89528 - FabianWolff:issue-89497, r=jackh726
Fix suggestion to borrow when casting from pointer to reference Fixes #89497.
2 parents 7d6feb4 + 388bcc1 commit f5bfa34

File tree

7 files changed

+80
-14
lines changed

7 files changed

+80
-14
lines changed

compiler/rustc_typeck/src/check/cast.rs

+36-8
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
351351
);
352352
let mut sugg = None;
353353
let mut sugg_mutref = false;
354-
if let ty::Ref(reg, _, mutbl) = *self.cast_ty.kind() {
354+
if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
355355
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() {
356356
if fcx
357357
.try_coerce(
@@ -366,7 +366,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
366366
)
367367
.is_ok()
368368
{
369-
sugg = Some(format!("&{}*", mutbl.prefix_str()));
369+
sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
370370
}
371371
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() {
372372
if expr_mutbl == Mutability::Not
@@ -400,7 +400,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
400400
)
401401
.is_ok()
402402
{
403-
sugg = Some(format!("&{}", mutbl.prefix_str()));
403+
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
404404
}
405405
} else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() {
406406
if fcx
@@ -416,19 +416,47 @@ impl<'a, 'tcx> CastCheck<'tcx> {
416416
)
417417
.is_ok()
418418
{
419-
sugg = Some(format!("&{}", mutbl.prefix_str()));
419+
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
420420
}
421421
}
422422
if sugg_mutref {
423423
err.span_label(self.span, "invalid cast");
424424
err.span_note(self.expr.span, "this reference is immutable");
425425
err.span_note(self.cast_span, "trying to cast to a mutable reference type");
426-
} else if let Some(sugg) = sugg {
426+
} else if let Some((sugg, remove_cast)) = sugg {
427427
err.span_label(self.span, "invalid cast");
428-
err.span_suggestion_verbose(
429-
self.expr.span.shrink_to_lo(),
428+
429+
let has_parens = fcx
430+
.tcx
431+
.sess
432+
.source_map()
433+
.span_to_snippet(self.expr.span)
434+
.map_or(false, |snip| snip.starts_with("("));
435+
436+
// Very crude check to see whether the expression must be wrapped
437+
// in parentheses for the suggestion to work (issue #89497).
438+
// Can/should be extended in the future.
439+
let needs_parens = !has_parens
440+
&& match self.expr.kind {
441+
hir::ExprKind::Cast(..) => true,
442+
_ => false,
443+
};
444+
445+
let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)];
446+
if needs_parens {
447+
suggestion[0].1 += "(";
448+
suggestion.push((self.expr.span.shrink_to_hi(), ")".to_string()));
449+
}
450+
if remove_cast {
451+
suggestion.push((
452+
self.expr.span.shrink_to_hi().to(self.cast_span),
453+
String::new(),
454+
));
455+
}
456+
457+
err.multipart_suggestion_verbose(
430458
"consider borrowing the value",
431-
sugg,
459+
suggestion,
432460
Applicability::MachineApplicable,
433461
);
434462
} else if !matches!(

src/test/ui/cast/issue-89497.fixed

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Regression test for issue #89497.
2+
3+
// run-rustfix
4+
5+
fn main() {
6+
let pointer: usize = &1_i32 as *const i32 as usize;
7+
let _reference: &'static i32 = unsafe { &*(pointer as *const i32) };
8+
//~^ ERROR: non-primitive cast
9+
//~| HELP: consider borrowing the value
10+
}

src/test/ui/cast/issue-89497.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Regression test for issue #89497.
2+
3+
// run-rustfix
4+
5+
fn main() {
6+
let pointer: usize = &1_i32 as *const i32 as usize;
7+
let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
8+
//~^ ERROR: non-primitive cast
9+
//~| HELP: consider borrowing the value
10+
}

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

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0605]: non-primitive cast: `*const i32` as `&'static i32`
2+
--> $DIR/issue-89497.rs:7:45
3+
|
4+
LL | let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
6+
|
7+
help: consider borrowing the value
8+
|
9+
LL - let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
10+
LL + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) };
11+
|
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0605`.

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ LL | v as &u8;
1212
|
1313
help: consider borrowing the value
1414
|
15-
LL | &*v as &u8;
16-
| ++
15+
LL - v as &u8;
16+
LL + &*v;
17+
|
1718

1819
error: aborting due to 2 previous errors
1920

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ LL | let _q: &isize = p as &isize;
66
|
77
help: consider borrowing the value
88
|
9-
LL | let _q: &isize = &*p as &isize;
10-
| ++
9+
LL - let _q: &isize = p as &isize;
10+
LL + let _q: &isize = &*p;
11+
|
1112

1213
error: aborting due to previous error
1314

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ LL | let _ = v as &u8;
2828
|
2929
help: consider borrowing the value
3030
|
31-
LL | let _ = &*v as &u8;
32-
| ++
31+
LL - let _ = v as &u8;
32+
LL + let _ = &*v;
33+
|
3334

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

0 commit comments

Comments
 (0)