add parentheses when unboxing suggestion needed

This commit is contained in:
Yihai Lin 2024-11-12 15:53:37 +08:00
parent 81eef2d362
commit 949cf61fdc
3 changed files with 101 additions and 9 deletions

View File

@ -2648,15 +2648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| {
let needs_parens = match expr.kind {
// parenthesize if needed (Issue #46756)
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
// parenthesize borrows of range literals (Issue #54505)
_ if is_range_literal(expr) => true,
_ => false,
};
if needs_parens {
if self.needs_parentheses(expr) {
(
vec![
(span.shrink_to_lo(), format!("{prefix}{sugg}(")),
@ -2869,6 +2861,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
}
if self.needs_parentheses(expr) {
return Some((
vec![
(span, format!("{suggestion}(")),
(expr.span.shrink_to_hi(), ")".to_string()),
],
message,
Applicability::MachineApplicable,
true,
false,
));
}
return Some((
vec![(span, suggestion)],
message,
@ -2897,6 +2902,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}
fn needs_parentheses(&self, expr: &hir::Expr<'_>) -> bool {
match expr.kind {
// parenthesize if needed (Issue #46756)
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
// parenthesize borrows of range literals (Issue #54505)
_ if is_range_literal(expr) => true,
_ => false,
}
}
pub(crate) fn suggest_cast(
&self,
err: &mut Diag<'_>,

View File

@ -0,0 +1,18 @@
//@ check-fail
fn main() {
let x = Box::new(Some(1));
let test: Option<i32> = x;
//~^ ERROR mismatched types
let x = Box::new(Some(1));
let test: Option<i32> = { x as Box<Option<i32>> };
//~^ ERROR mismatched types
let x = Box::new(Some(1));
let test: Option<i32> = if true { x as Box<Option<i32>> } else { None };
//~^ ERROR mismatched types
let x = std::rc::Rc::new(Some(1));
let test: Option<i32> = x as std::rc::Rc<Option<i32>>;
//~^ ERROR mismatched types
}

View File

@ -0,0 +1,59 @@
error[E0308]: mismatched types
--> $DIR/unboxing-needing-parenthases-issue-132924.rs:5:29
|
LL | let test: Option<i32> = x;
| ----------- ^ expected `Option<i32>`, found `Box<Option<{integer}>>`
| |
| expected due to this
|
= note: expected enum `Option<i32>`
found struct `Box<Option<{integer}>>`
help: consider unboxing the value
|
LL | let test: Option<i32> = *x;
| +
error[E0308]: mismatched types
--> $DIR/unboxing-needing-parenthases-issue-132924.rs:8:31
|
LL | let test: Option<i32> = { x as Box<Option<i32>> };
| ^^^^^^^^^^^^^^^^^^^^^ expected `Option<i32>`, found `Box<Option<i32>>`
|
= note: expected enum `Option<_>`
found struct `Box<Option<_>>`
help: consider unboxing the value
|
LL | let test: Option<i32> = { *(x as Box<Option<i32>>) };
| ++ +
error[E0308]: mismatched types
--> $DIR/unboxing-needing-parenthases-issue-132924.rs:12:39
|
LL | let test: Option<i32> = if true { x as Box<Option<i32>> } else { None };
| ^^^^^^^^^^^^^^^^^^^^^ expected `Option<i32>`, found `Box<Option<i32>>`
|
= note: expected enum `Option<_>`
found struct `Box<Option<_>>`
help: consider unboxing the value
|
LL | let test: Option<i32> = if true { *(x as Box<Option<i32>>) } else { None };
| ++ +
error[E0308]: mismatched types
--> $DIR/unboxing-needing-parenthases-issue-132924.rs:16:29
|
LL | let test: Option<i32> = x as std::rc::Rc<Option<i32>>;
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<i32>`, found `Rc<Option<i32>>`
| |
| expected due to this
|
= note: expected enum `Option<_>`
found struct `Rc<Option<_>>`
help: consider dereferencing the type
|
LL | let test: Option<i32> = *(x as std::rc::Rc<Option<i32>>);
| ++ +
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.