diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 919e83724d70a..910beed2eeccf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -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.is_need_parenthesize(expr) { ( vec![ (span.shrink_to_lo(), format!("{prefix}{sugg}(")), @@ -2869,6 +2861,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } + if checked_ty.is_box() && self.is_need_parenthesize(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 is_need_parenthesize(&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<'_>, diff --git a/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.rs b/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.rs new file mode 100644 index 0000000000000..45018e9f79ba9 --- /dev/null +++ b/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.rs @@ -0,0 +1,14 @@ +//@ check-fail +fn main() { + let x = Box::new(Some(1)); + + let test: Option = x; + //~^ ERROR mismatched types + let x = Box::new(Some(1)); + let test: Option = { x as Box> }; + //~^ ERROR mismatched types + + let x = Box::new(Some(1)); + let test: Option = if true { x as Box> } else { None }; + //~^ ERROR mismatched types +} diff --git a/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.stderr b/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.stderr new file mode 100644 index 0000000000000..b166730a6b2b0 --- /dev/null +++ b/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.stderr @@ -0,0 +1,44 @@ +error[E0308]: mismatched types + --> $DIR/unboxing-needing-parenthases-issue-132924.rs:5:29 + | +LL | let test: Option = x; + | ----------- ^ expected `Option`, found `Box>` + | | + | expected due to this + | + = note: expected enum `Option` + found struct `Box>` +help: consider unboxing the value + | +LL | let test: Option = *x; + | + + +error[E0308]: mismatched types + --> $DIR/unboxing-needing-parenthases-issue-132924.rs:8:31 + | +LL | let test: Option = { x as Box> }; + | ^^^^^^^^^^^^^^^^^^^^^ expected `Option`, found `Box>` + | + = note: expected enum `Option<_>` + found struct `Box>` +help: consider unboxing the value + | +LL | let test: Option = { *(x as Box>) }; + | ++ + + +error[E0308]: mismatched types + --> $DIR/unboxing-needing-parenthases-issue-132924.rs:12:39 + | +LL | let test: Option = if true { x as Box> } else { None }; + | ^^^^^^^^^^^^^^^^^^^^^ expected `Option`, found `Box>` + | + = note: expected enum `Option<_>` + found struct `Box>` +help: consider unboxing the value + | +LL | let test: Option = if true { *(x as Box>) } else { None }; + | ++ + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`.