diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 148e0a24ec304..beffbe410ba16 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1919,17 +1919,13 @@ impl<'a> Parser<'a> {
         match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) {
             Ok(arr) => {
                 let hi = snapshot.prev_token.span;
-                self.struct_span_err(
-                    arr.span,
-                    "this code is interpreted as a block expression, not an array",
-                )
-                .multipart_suggestion(
-                    "try using [] instead of {}",
-                    vec![(lo, "[".to_owned()), (hi, "]".to_owned())],
-                    Applicability::MaybeIncorrect,
-                )
-                .note("to define an array, one would use square brackets instead of curly braces")
-                .emit();
+                self.struct_span_err(arr.span, "this is a block expression, not an array")
+                    .multipart_suggestion(
+                        "to make an array, use square brackets instead of curly braces",
+                        vec![(lo, "[".to_owned()), (hi, "]".to_owned())],
+                        Applicability::MaybeIncorrect,
+                    )
+                    .emit();
 
                 self.restore_snapshot(snapshot);
                 Some(self.mk_expr_err(arr.span))
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 58e5c9315c30c..b9d7c1ea1c638 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -39,6 +39,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.suggest_no_capture_closure(err, expected, expr_ty);
         self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
         self.suggest_missing_parentheses(err, expr);
+        self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected);
         self.note_need_for_fn_pointer(err, expected, expr_ty);
         self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
         self.report_closure_inferred_return_type(err, expected);
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index b7b45929e1463..29cefe63c0b94 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -774,57 +774,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let prev_diverges = self.diverges.get();
         let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
 
-        let (ctxt, ()) =
-            self.with_breakable_ctxt(blk.hir_id, ctxt, || {
-                for (pos, s) in blk.stmts.iter().enumerate() {
-                    self.check_stmt(s, blk.stmts.len() - 1 == pos);
-                }
+        let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
+            for (pos, s) in blk.stmts.iter().enumerate() {
+                self.check_stmt(s, blk.stmts.len() - 1 == pos);
+            }
 
-                // check the tail expression **without** holding the
-                // `enclosing_breakables` lock below.
-                let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
-
-                let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
-                let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
-                let coerce = ctxt.coerce.as_mut().unwrap();
-                if let Some(tail_expr_ty) = tail_expr_ty {
-                    let tail_expr = tail_expr.unwrap();
-                    let span = self.get_expr_coercion_span(tail_expr);
-                    let cause =
-                        self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
-                    coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
-                } else {
-                    // Subtle: if there is no explicit tail expression,
-                    // that is typically equivalent to a tail expression
-                    // of `()` -- except if the block diverges. In that
-                    // case, there is no value supplied from the tail
-                    // expression (assuming there are no other breaks,
-                    // this implies that the type of the block will be
-                    // `!`).
-                    //
-                    // #41425 -- label the implicit `()` as being the
-                    // "found type" here, rather than the "expected type".
-                    if !self.diverges.get().is_always() {
-                        // #50009 -- Do not point at the entire fn block span, point at the return type
-                        // span, as it is the cause of the requirement, and
-                        // `consider_hint_about_removing_semicolon` will point at the last expression
-                        // if it were a relevant part of the error. This improves usability in editors
-                        // that highlight errors inline.
-                        let mut sp = blk.span;
-                        let mut fn_span = None;
-                        if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
-                            let ret_sp = decl.output.span();
-                            if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
-                                // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
-                                // output would otherwise be incorrect and even misleading. Make sure
-                                // the span we're aiming at correspond to a `fn` body.
-                                if block_sp == blk.span {
-                                    sp = ret_sp;
-                                    fn_span = Some(ident.span);
-                                }
+            // check the tail expression **without** holding the
+            // `enclosing_breakables` lock below.
+            let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
+
+            let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+            let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
+            let coerce = ctxt.coerce.as_mut().unwrap();
+            if let Some(tail_expr_ty) = tail_expr_ty {
+                let tail_expr = tail_expr.unwrap();
+                let span = self.get_expr_coercion_span(tail_expr);
+                let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
+                let ty_for_diagnostic = coerce.merged_ty();
+                // We use coerce_inner here because we want to augment the error
+                // suggesting to wrap the block in square brackets if it might've
+                // been mistaken array syntax
+                coerce.coerce_inner(
+                    self,
+                    &cause,
+                    Some(tail_expr),
+                    tail_expr_ty,
+                    Some(&mut |diag: &mut Diagnostic| {
+                        self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
+                    }),
+                    false,
+                );
+            } else {
+                // Subtle: if there is no explicit tail expression,
+                // that is typically equivalent to a tail expression
+                // of `()` -- except if the block diverges. In that
+                // case, there is no value supplied from the tail
+                // expression (assuming there are no other breaks,
+                // this implies that the type of the block will be
+                // `!`).
+                //
+                // #41425 -- label the implicit `()` as being the
+                // "found type" here, rather than the "expected type".
+                if !self.diverges.get().is_always() {
+                    // #50009 -- Do not point at the entire fn block span, point at the return type
+                    // span, as it is the cause of the requirement, and
+                    // `consider_hint_about_removing_semicolon` will point at the last expression
+                    // if it were a relevant part of the error. This improves usability in editors
+                    // that highlight errors inline.
+                    let mut sp = blk.span;
+                    let mut fn_span = None;
+                    if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
+                        let ret_sp = decl.output.span();
+                        if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
+                            // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
+                            // output would otherwise be incorrect and even misleading. Make sure
+                            // the span we're aiming at correspond to a `fn` body.
+                            if block_sp == blk.span {
+                                sp = ret_sp;
+                                fn_span = Some(ident.span);
                             }
                         }
-                        coerce.coerce_forced_unit(
+                    }
+                    coerce.coerce_forced_unit(
                         self,
                         &self.misc(sp),
                         &mut |err| {
@@ -837,21 +848,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     // Our block must be a `assign desugar local; assignment`
                                     if let Some(hir::Node::Block(hir::Block {
                                         stmts:
-                                            [hir::Stmt {
-                                                kind:
-                                                    hir::StmtKind::Local(hir::Local {
-                                                        source: hir::LocalSource::AssignDesugar(_),
-                                                        ..
-                                                    }),
-                                                ..
-                                            }, hir::Stmt {
-                                                kind:
-                                                    hir::StmtKind::Expr(hir::Expr {
-                                                        kind: hir::ExprKind::Assign(..),
-                                                        ..
-                                                    }),
-                                                ..
-                                            }],
+                                            [
+                                                hir::Stmt {
+                                                    kind:
+                                                        hir::StmtKind::Local(hir::Local {
+                                                            source:
+                                                                hir::LocalSource::AssignDesugar(_),
+                                                            ..
+                                                        }),
+                                                    ..
+                                                },
+                                                hir::Stmt {
+                                                    kind:
+                                                        hir::StmtKind::Expr(hir::Expr {
+                                                            kind: hir::ExprKind::Assign(..),
+                                                            ..
+                                                        }),
+                                                    ..
+                                                },
+                                            ],
                                         ..
                                     })) = self.tcx.hir().find(blk.hir_id)
                                     {
@@ -871,9 +886,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         },
                         false,
                     );
-                    }
                 }
-            });
+            }
+        });
 
         if ctxt.may_break {
             // If we can break from the block, then the block's exit is always reachable
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 67d61668b6d85..1ff4008ccdff3 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -757,6 +757,77 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// Given an expression type mismatch, peel any `&` expressions until we get to
+    /// a block expression, and then suggest replacing the braces with square braces
+    /// if it was possibly mistaken array syntax.
+    pub(crate) fn suggest_block_to_brackets_peeling_refs(
+        &self,
+        diag: &mut Diagnostic,
+        mut expr: &hir::Expr<'_>,
+        mut expr_ty: Ty<'tcx>,
+        mut expected_ty: Ty<'tcx>,
+    ) {
+        loop {
+            match (&expr.kind, expr_ty.kind(), expected_ty.kind()) {
+                (
+                    hir::ExprKind::AddrOf(_, _, inner_expr),
+                    ty::Ref(_, inner_expr_ty, _),
+                    ty::Ref(_, inner_expected_ty, _),
+                ) => {
+                    expr = *inner_expr;
+                    expr_ty = *inner_expr_ty;
+                    expected_ty = *inner_expected_ty;
+                }
+                (hir::ExprKind::Block(blk, _), _, _) => {
+                    self.suggest_block_to_brackets(diag, *blk, expr_ty, expected_ty);
+                    break;
+                }
+                _ => break,
+            }
+        }
+    }
+
+    /// Suggest wrapping the block in square brackets instead of curly braces
+    /// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
+    pub(crate) fn suggest_block_to_brackets(
+        &self,
+        diag: &mut Diagnostic,
+        blk: &hir::Block<'_>,
+        blk_ty: Ty<'tcx>,
+        expected_ty: Ty<'tcx>,
+    ) {
+        if let ty::Slice(elem_ty) | ty::Array(elem_ty, _) = expected_ty.kind() {
+            if self.can_coerce(blk_ty, *elem_ty)
+                && blk.stmts.is_empty()
+                && blk.rules == hir::BlockCheckMode::DefaultBlock
+            {
+                let source_map = self.tcx.sess.source_map();
+                if let Ok(snippet) = source_map.span_to_snippet(blk.span) {
+                    if snippet.starts_with('{') && snippet.ends_with('}') {
+                        diag.multipart_suggestion_verbose(
+                            "to create an array, use square brackets instead of curly braces",
+                            vec![
+                                (
+                                    blk.span
+                                        .shrink_to_lo()
+                                        .with_hi(rustc_span::BytePos(blk.span.lo().0 + 1)),
+                                    "[".to_string(),
+                                ),
+                                (
+                                    blk.span
+                                        .shrink_to_hi()
+                                        .with_lo(rustc_span::BytePos(blk.span.hi().0 - 1)),
+                                    "]".to_string(),
+                                ),
+                            ],
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                }
+            }
+        }
+    }
+
     fn is_loop(&self, id: hir::HirId) -> bool {
         let node = self.tcx.hir().get(id);
         matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
diff --git a/src/test/ui/did_you_mean/brackets-to-braces-single-element.rs b/src/test/ui/did_you_mean/brackets-to-braces-single-element.rs
new file mode 100644
index 0000000000000..4d0109767fc0f
--- /dev/null
+++ b/src/test/ui/did_you_mean/brackets-to-braces-single-element.rs
@@ -0,0 +1,10 @@
+const A: [&str; 1] = { "hello" };
+//~^ ERROR mismatched types
+
+const B: &[u32] = &{ 1 };
+//~^ ERROR mismatched types
+
+const C: &&[u32; 1] = &&{ 1 };
+//~^ ERROR mismatched types
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/brackets-to-braces-single-element.stderr b/src/test/ui/did_you_mean/brackets-to-braces-single-element.stderr
new file mode 100644
index 0000000000000..6ded03e45b55e
--- /dev/null
+++ b/src/test/ui/did_you_mean/brackets-to-braces-single-element.stderr
@@ -0,0 +1,38 @@
+error[E0308]: mismatched types
+  --> $DIR/brackets-to-braces-single-element.rs:1:24
+   |
+LL | const A: [&str; 1] = { "hello" };
+   |                        ^^^^^^^ expected array `[&'static str; 1]`, found `&str`
+   |
+help: to create an array, use square brackets instead of curly braces
+   |
+LL | const A: [&str; 1] = [ "hello" ];
+   |                      ~         ~
+
+error[E0308]: mismatched types
+  --> $DIR/brackets-to-braces-single-element.rs:4:19
+   |
+LL | const B: &[u32] = &{ 1 };
+   |                   ^^^^^^ expected slice `[u32]`, found integer
+   |
+   = note: expected reference `&'static [u32]`
+              found reference `&{integer}`
+help: to create an array, use square brackets instead of curly braces
+   |
+LL | const B: &[u32] = &[ 1 ];
+   |                    ~   ~
+
+error[E0308]: mismatched types
+  --> $DIR/brackets-to-braces-single-element.rs:7:27
+   |
+LL | const C: &&[u32; 1] = &&{ 1 };
+   |                           ^ expected array `[u32; 1]`, found integer
+   |
+help: to create an array, use square brackets instead of curly braces
+   |
+LL | const C: &&[u32; 1] = &&[ 1 ];
+   |                         ~   ~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs
index 53dad85900a65..070ffaa1eff00 100644
--- a/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs
+++ b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs
@@ -1,15 +1,16 @@
 fn main() {}
 
-const FOO: [u8; 3] = { //~ ERROR this code is interpreted as a block expression
+const FOO: [u8; 3] = {
+    //~^ ERROR this is a block expression, not an array
     1, 2, 3
 };
 
 const BAR: [&str; 3] = {"one", "two", "three"};
-//~^ ERROR this code is interpreted as a block expression
+//~^ ERROR this is a block expression, not an array
 
 fn foo() {
     {1, 2, 3};
-    //~^ ERROR this code is interpreted as a block expression
+    //~^ ERROR this is a block expression, not an array
 }
 
 fn bar() {
diff --git a/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr
index 9ab491f5c238f..d5ad1a72b8250 100644
--- a/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr
+++ b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr
@@ -1,46 +1,45 @@
-error: this code is interpreted as a block expression, not an array
+error: this is a block expression, not an array
   --> $DIR/issue-87830-try-brackets-for-arrays.rs:3:22
    |
 LL |   const FOO: [u8; 3] = {
    |  ______________________^
+LL | |
 LL | |     1, 2, 3
 LL | | };
    | |_^
    |
-   = note: to define an array, one would use square brackets instead of curly braces
-help: try using [] instead of {}
+help: to make an array, use square brackets instead of curly braces
    |
 LL ~ const FOO: [u8; 3] = [
+LL |
 LL |     1, 2, 3
 LL ~ ];
    |
 
-error: this code is interpreted as a block expression, not an array
-  --> $DIR/issue-87830-try-brackets-for-arrays.rs:7:24
+error: this is a block expression, not an array
+  --> $DIR/issue-87830-try-brackets-for-arrays.rs:8:24
    |
 LL | const BAR: [&str; 3] = {"one", "two", "three"};
    |                        ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: to define an array, one would use square brackets instead of curly braces
-help: try using [] instead of {}
+help: to make an array, use square brackets instead of curly braces
    |
 LL | const BAR: [&str; 3] = ["one", "two", "three"];
    |                        ~                     ~
 
-error: this code is interpreted as a block expression, not an array
-  --> $DIR/issue-87830-try-brackets-for-arrays.rs:11:5
+error: this is a block expression, not an array
+  --> $DIR/issue-87830-try-brackets-for-arrays.rs:12:5
    |
 LL |     {1, 2, 3};
    |     ^^^^^^^^^
    |
-   = note: to define an array, one would use square brackets instead of curly braces
-help: try using [] instead of {}
+help: to make an array, use square brackets instead of curly braces
    |
 LL |     [1, 2, 3];
    |     ~       ~
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
-  --> $DIR/issue-87830-try-brackets-for-arrays.rs:16:6
+  --> $DIR/issue-87830-try-brackets-for-arrays.rs:17:6
    |
 LL |     1, 2, 3
    |      ^ expected one of `.`, `;`, `?`, `}`, or an operator