diff --git a/src/libcore/array/iter.rs b/src/libcore/array/iter.rs
index 80eaae0d4afb5..f6b8d4ba08146 100644
--- a/src/libcore/array/iter.rs
+++ b/src/libcore/array/iter.rs
@@ -39,7 +39,7 @@ where
     alive: Range<usize>,
 }
 
-impl<T, const N: usize> IntoIter<T, { N }>
+impl<T, const N: usize> IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -99,7 +99,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> Iterator for IntoIter<T, { N }>
+impl<T, const N: usize> Iterator for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -146,7 +146,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, { N }>
+impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -182,7 +182,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> Drop for IntoIter<T, { N }>
+impl<T, const N: usize> Drop for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -195,7 +195,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> ExactSizeIterator for IntoIter<T, { N }>
+impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -210,17 +210,17 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> FusedIterator for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
+impl<T, const N: usize> FusedIterator for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
 
 // The iterator indeed reports the correct length. The number of "alive"
 // elements (that will still be yielded) is the length of the range `alive`.
 // This range is decremented in length in either `next` or `next_back`. It is
 // always decremented by 1 in those methods, but only if `Some(_)` is returned.
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
+unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T: Clone, const N: usize> Clone for IntoIter<T, { N }>
+impl<T: Clone, const N: usize> Clone for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -249,7 +249,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, { N }>
+impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs
index 34da29c974777..018e9da243c70 100644
--- a/src/librustc_lint/early.rs
+++ b/src/librustc_lint/early.rs
@@ -104,6 +104,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         run_early_pass!(self, check_pat_post, p);
     }
 
+    fn visit_anon_const(&mut self, c: &'a ast::AnonConst) {
+        run_early_pass!(self, check_anon_const, c);
+        ast_visit::walk_anon_const(self, c);
+    }
+
     fn visit_expr(&mut self, e: &'a ast::Expr) {
         self.with_lint_attrs(e.id, &e.attrs, |cx| {
             run_early_pass!(cx, check_expr, e);
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 825ac04bc0920..1b92e77558505 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -104,6 +104,7 @@ macro_rules! early_lint_passes {
             $args,
             [
                 UnusedParens: UnusedParens,
+                UnusedBraces: UnusedBraces,
                 UnusedImportBraces: UnusedImportBraces,
                 UnsafeCode: UnsafeCode,
                 AnonymousParameters: AnonymousParameters,
@@ -275,6 +276,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
         UNUSED_FEATURES,
         UNUSED_LABELS,
         UNUSED_PARENS,
+        UNUSED_BRACES,
         REDUNDANT_SEMICOLONS
     );
 
diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs
index ace154714458e..c9e12afedbbab 100644
--- a/src/librustc_lint/passes.rs
+++ b/src/librustc_lint/passes.rs
@@ -170,6 +170,7 @@ macro_rules! early_lint_methods {
             fn check_stmt(a: &ast::Stmt);
             fn check_arm(a: &ast::Arm);
             fn check_pat(a: &ast::Pat);
+            fn check_anon_const(a: &ast::AnonConst);
             fn check_pat_post(a: &ast::Pat);
             fn check_expr(a: &ast::Expr);
             fn check_expr_post(a: &ast::Expr);
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index b5826d6a5efa6..51f91aa6fb792 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -1,7 +1,9 @@
+use crate::Lint;
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc::ty::adjustment;
 use rustc::ty::{self, Ty};
 use rustc_ast::ast;
+use rustc_ast::ast::{ExprKind, StmtKind};
 use rustc_ast::attr;
 use rustc_ast::util::parser;
 use rustc_ast_pretty::pprust;
@@ -318,16 +320,58 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
     }
 }
 
-declare_lint! {
-    pub(super) UNUSED_PARENS,
-    Warn,
-    "`if`, `match`, `while` and `return` do not need parentheses"
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum UnusedDelimsCtx {
+    FunctionArg,
+    MethodArg,
+    AssignedValue,
+    IfCond,
+    WhileCond,
+    ForIterExpr,
+    MatchScrutineeExpr,
+    ReturnValue,
+    BlockRetValue,
+    LetScrutineeExpr,
+    ArrayLenExpr,
+    AnonConst,
 }
 
-declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
+impl From<UnusedDelimsCtx> for &'static str {
+    fn from(ctx: UnusedDelimsCtx) -> &'static str {
+        match ctx {
+            UnusedDelimsCtx::FunctionArg => "function argument",
+            UnusedDelimsCtx::MethodArg => "method argument",
+            UnusedDelimsCtx::AssignedValue => "assigned value",
+            UnusedDelimsCtx::IfCond => "`if` condition",
+            UnusedDelimsCtx::WhileCond => "`while` condition",
+            UnusedDelimsCtx::ForIterExpr => "`for` iterator expression",
+            UnusedDelimsCtx::MatchScrutineeExpr => "`match` scrutinee expression",
+            UnusedDelimsCtx::ReturnValue => "`return` value",
+            UnusedDelimsCtx::BlockRetValue => "block return value",
+            UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
+            UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
+        }
+    }
+}
 
-impl UnusedParens {
-    fn is_expr_parens_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
+/// Used by both `UnusedParens` and `UnusedBraces` to prevent code duplication.
+trait UnusedDelimLint {
+    const DELIM_STR: &'static str;
+
+    // this cannot be a constant is it refers to a static.
+    fn lint(&self) -> &'static Lint;
+
+    fn check_unused_delims_expr(
+        &self,
+        cx: &EarlyContext<'_>,
+        value: &ast::Expr,
+        ctx: UnusedDelimsCtx,
+        followed_by_block: bool,
+        left_pos: Option<BytePos>,
+        right_pos: Option<BytePos>,
+    );
+
+    fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
         followed_by_block
             && match inner.kind {
                 ast::ExprKind::Ret(_) | ast::ExprKind::Break(..) => true,
@@ -335,98 +379,41 @@ impl UnusedParens {
             }
     }
 
-    fn check_unused_parens_expr(
+    fn emit_unused_delims_expr(
         &self,
         cx: &EarlyContext<'_>,
         value: &ast::Expr,
-        msg: &str,
-        followed_by_block: bool,
+        ctx: UnusedDelimsCtx,
         left_pos: Option<BytePos>,
         right_pos: Option<BytePos>,
     ) {
-        match value.kind {
-            ast::ExprKind::Paren(ref inner) => {
-                if !Self::is_expr_parens_necessary(inner, followed_by_block)
-                    && value.attrs.is_empty()
-                    && !value.span.from_expansion()
-                {
-                    let expr_text =
-                        if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
-                            snippet
-                        } else {
-                            pprust::expr_to_string(value)
-                        };
-                    let keep_space = (
-                        left_pos.map(|s| s >= value.span.lo()).unwrap_or(false),
-                        right_pos.map(|s| s <= value.span.hi()).unwrap_or(false),
-                    );
-                    Self::remove_outer_parens(cx, value.span, &expr_text, msg, keep_space);
-                }
-            }
-            ast::ExprKind::Let(_, ref expr) => {
-                // FIXME(#60336): Properly handle `let true = (false && true)`
-                // actually needing the parenthesis.
-                self.check_unused_parens_expr(
-                    cx,
-                    expr,
-                    "`let` head expression",
-                    followed_by_block,
-                    None,
-                    None,
-                );
-            }
-            _ => {}
-        }
+        let expr_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
+            snippet
+        } else {
+            pprust::expr_to_string(value)
+        };
+        let keep_space = (
+            left_pos.map(|s| s >= value.span.lo()).unwrap_or(false),
+            right_pos.map(|s| s <= value.span.hi()).unwrap_or(false),
+        );
+        self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space);
     }
 
-    fn check_unused_parens_pat(
+    fn emit_unused_delims(
         &self,
-        cx: &EarlyContext<'_>,
-        value: &ast::Pat,
-        avoid_or: bool,
-        avoid_mut: bool,
-    ) {
-        use ast::{BindingMode, Mutability, PatKind};
-
-        if let PatKind::Paren(inner) = &value.kind {
-            match inner.kind {
-                // The lint visitor will visit each subpattern of `p`. We do not want to lint
-                // any range pattern no matter where it occurs in the pattern. For something like
-                // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
-                // that if there are unnecessary parens they serve a purpose of readability.
-                PatKind::Range(..) => return,
-                // Avoid `p0 | .. | pn` if we should.
-                PatKind::Or(..) if avoid_or => return,
-                // Avoid `mut x` and `mut x @ p` if we should:
-                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return,
-                // Otherwise proceed with linting.
-                _ => {}
-            }
-
-            let pattern_text =
-                if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
-                    snippet
-                } else {
-                    pprust::pat_to_string(value)
-                };
-            Self::remove_outer_parens(cx, value.span, &pattern_text, "pattern", (false, false));
-        }
-    }
-
-    fn remove_outer_parens(
         cx: &EarlyContext<'_>,
         span: Span,
         pattern: &str,
         msg: &str,
         keep_space: (bool, bool),
     ) {
-        cx.struct_span_lint(UNUSED_PARENS, span, |lint| {
-            let span_msg = format!("unnecessary parentheses around {}", msg);
+        cx.struct_span_lint(self.lint(), span, |lint| {
+            let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg);
             let mut err = lint.build(&span_msg);
             let mut ate_left_paren = false;
             let mut ate_right_paren = false;
             let parens_removed = pattern.trim_matches(|c| match c {
-                '(' => {
+                '(' | '{' => {
                     if ate_left_paren {
                         false
                     } else {
@@ -434,7 +421,7 @@ impl UnusedParens {
                         true
                     }
                 }
-                ')' => {
+                ')' | '}' => {
                     if ate_right_paren {
                         false
                     } else {
@@ -460,61 +447,51 @@ impl UnusedParens {
                 replace
             };
 
-            err.span_suggestion_short(
-                span,
-                "remove these parentheses",
-                replace,
-                Applicability::MachineApplicable,
-            );
+            let suggestion = format!("remove these {}", Self::DELIM_STR);
+
+            err.span_suggestion_short(span, &suggestion, replace, Applicability::MachineApplicable);
             err.emit();
         });
     }
-}
 
-impl EarlyLintPass for UnusedParens {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         use rustc_ast::ast::ExprKind::*;
-        let (value, msg, followed_by_block, left_pos, right_pos) = match e.kind {
-            Let(ref pat, ..) => {
-                self.check_unused_parens_pat(cx, pat, false, false);
-                return;
-            }
-
+        let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
             If(ref cond, ref block, ..) => {
                 let left = e.span.lo() + rustc_span::BytePos(2);
                 let right = block.span.lo();
-                (cond, "`if` condition", true, Some(left), Some(right))
+                (cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right))
             }
 
             While(ref cond, ref block, ..) => {
                 let left = e.span.lo() + rustc_span::BytePos(5);
                 let right = block.span.lo();
-                (cond, "`while` condition", true, Some(left), Some(right))
+                (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right))
             }
 
-            ForLoop(ref pat, ref cond, ref block, ..) => {
-                self.check_unused_parens_pat(cx, pat, false, false);
-                (cond, "`for` head expression", true, None, Some(block.span.lo()))
+            ForLoop(_, ref cond, ref block, ..) => {
+                (cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()))
             }
 
             Match(ref head, _) => {
                 let left = e.span.lo() + rustc_span::BytePos(5);
-                (head, "`match` head expression", true, Some(left), None)
+                (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None)
             }
 
             Ret(Some(ref value)) => {
                 let left = e.span.lo() + rustc_span::BytePos(3);
-                (value, "`return` value", false, Some(left), None)
+                (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None)
             }
 
-            Assign(_, ref value, _) => (value, "assigned value", false, None, None),
-            AssignOp(.., ref value) => (value, "assigned value", false, None, None),
+            Assign(_, ref value, _) | AssignOp(.., ref value) => {
+                (value, UnusedDelimsCtx::AssignedValue, false, None, None)
+            }
             // either function/method call, or something this lint doesn't care about
             ref call_or_other => {
-                let (args_to_check, call_kind) = match *call_or_other {
-                    Call(_, ref args) => (&args[..], "function"),
-                    // first "argument" is self (which sometimes needs parens)
-                    MethodCall(_, ref args) => (&args[1..], "method"),
+                let (args_to_check, ctx) = match *call_or_other {
+                    Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
+                    // first "argument" is self (which sometimes needs delims)
+                    MethodCall(_, ref args) => (&args[1..], UnusedDelimsCtx::MethodArg),
                     // actual catch-all arm
                     _ => {
                         return;
@@ -527,14 +504,152 @@ impl EarlyLintPass for UnusedParens {
                 if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
                     return;
                 }
-                let msg = format!("{} argument", call_kind);
                 for arg in args_to_check {
-                    self.check_unused_parens_expr(cx, arg, &msg, false, None, None);
+                    self.check_unused_delims_expr(cx, arg, ctx, false, None, None);
                 }
                 return;
             }
         };
-        self.check_unused_parens_expr(cx, &value, msg, followed_by_block, left_pos, right_pos);
+        self.check_unused_delims_expr(cx, &value, ctx, followed_by_block, left_pos, right_pos);
+    }
+
+    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
+        match s.kind {
+            StmtKind::Local(ref local) => {
+                if let Some(ref value) = local.init {
+                    self.check_unused_delims_expr(
+                        cx,
+                        &value,
+                        UnusedDelimsCtx::AssignedValue,
+                        false,
+                        None,
+                        None,
+                    );
+                }
+            }
+            StmtKind::Expr(ref expr) => {
+                self.check_unused_delims_expr(
+                    cx,
+                    &expr,
+                    UnusedDelimsCtx::BlockRetValue,
+                    false,
+                    None,
+                    None,
+                );
+            }
+            _ => {}
+        }
+    }
+
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
+        use ast::ItemKind::*;
+
+        if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind {
+            self.check_unused_delims_expr(
+                cx,
+                expr,
+                UnusedDelimsCtx::AssignedValue,
+                false,
+                None,
+                None,
+            );
+        }
+    }
+}
+
+declare_lint! {
+    pub(super) UNUSED_PARENS,
+    Warn,
+    "`if`, `match`, `while` and `return` do not need parentheses"
+}
+
+declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
+
+impl UnusedDelimLint for UnusedParens {
+    const DELIM_STR: &'static str = "parentheses";
+
+    fn lint(&self) -> &'static Lint {
+        UNUSED_PARENS
+    }
+
+    fn check_unused_delims_expr(
+        &self,
+        cx: &EarlyContext<'_>,
+        value: &ast::Expr,
+        ctx: UnusedDelimsCtx,
+        followed_by_block: bool,
+        left_pos: Option<BytePos>,
+        right_pos: Option<BytePos>,
+    ) {
+        match value.kind {
+            ast::ExprKind::Paren(ref inner) => {
+                if !Self::is_expr_delims_necessary(inner, followed_by_block)
+                    && value.attrs.is_empty()
+                    && !value.span.from_expansion()
+                {
+                    self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
+                }
+            }
+            ast::ExprKind::Let(_, ref expr) => {
+                // FIXME(#60336): Properly handle `let true = (false && true)`
+                // actually needing the parenthesis.
+                self.check_unused_delims_expr(
+                    cx,
+                    expr,
+                    UnusedDelimsCtx::LetScrutineeExpr,
+                    followed_by_block,
+                    None,
+                    None,
+                );
+            }
+            _ => {}
+        }
+    }
+}
+
+impl UnusedParens {
+    fn check_unused_parens_pat(
+        &self,
+        cx: &EarlyContext<'_>,
+        value: &ast::Pat,
+        avoid_or: bool,
+        avoid_mut: bool,
+    ) {
+        use ast::{BindingMode, Mutability, PatKind};
+
+        if let PatKind::Paren(inner) = &value.kind {
+            match inner.kind {
+                // The lint visitor will visit each subpattern of `p`. We do not want to lint
+                // any range pattern no matter where it occurs in the pattern. For something like
+                // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
+                // that if there are unnecessary parens they serve a purpose of readability.
+                PatKind::Range(..) => return,
+                // Avoid `p0 | .. | pn` if we should.
+                PatKind::Or(..) if avoid_or => return,
+                // Avoid `mut x` and `mut x @ p` if we should:
+                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return,
+                // Otherwise proceed with linting.
+                _ => {}
+            }
+
+            let pattern_text =
+                if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
+                    snippet
+                } else {
+                    pprust::pat_to_string(value)
+                };
+            self.emit_unused_delims(cx, value.span, &pattern_text, "pattern", (false, false));
+        }
+    }
+}
+
+impl EarlyLintPass for UnusedParens {
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
+        if let ExprKind::Let(ref pat, ..) | ExprKind::ForLoop(ref pat, ..) = e.kind {
+            self.check_unused_parens_pat(cx, pat, false, false);
+        }
+
+        <Self as UnusedDelimLint>::check_expr(self, cx, e)
     }
 
     fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
@@ -559,22 +674,16 @@ impl EarlyLintPass for UnusedParens {
         }
     }
 
-    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
-        use ast::StmtKind::*;
-
-        match s.kind {
-            Local(ref local) => {
-                self.check_unused_parens_pat(cx, &local.pat, false, false);
+    fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) {
+        self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None);
+    }
 
-                if let Some(ref value) = local.init {
-                    self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None);
-                }
-            }
-            Expr(ref expr) => {
-                self.check_unused_parens_expr(cx, &expr, "block return value", false, None, None);
-            }
-            _ => {}
+    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
+        if let StmtKind::Local(ref local) = s.kind {
+            self.check_unused_parens_pat(cx, &local.pat, false, false);
         }
+
+        <Self as UnusedDelimLint>::check_stmt(self, cx, s)
     }
 
     fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
@@ -590,6 +699,16 @@ impl EarlyLintPass for UnusedParens {
             match &r.kind {
                 &ast::TyKind::TraitObject(..) => {}
                 &ast::TyKind::ImplTrait(_, ref bounds) if bounds.len() > 1 => {}
+                &ast::TyKind::Array(_, ref len) => {
+                    self.check_unused_delims_expr(
+                        cx,
+                        &len.value,
+                        UnusedDelimsCtx::ArrayLenExpr,
+                        false,
+                        None,
+                        None,
+                    );
+                }
                 _ => {
                     let pattern_text =
                         if let Ok(snippet) = cx.sess().source_map().span_to_snippet(ty.span) {
@@ -598,19 +717,134 @@ impl EarlyLintPass for UnusedParens {
                             pprust::ty_to_string(ty)
                         };
 
-                    Self::remove_outer_parens(cx, ty.span, &pattern_text, "type", (false, false));
+                    self.emit_unused_delims(cx, ty.span, &pattern_text, "type", (false, false));
                 }
             }
         }
     }
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
-        use ast::ItemKind::*;
+        <Self as UnusedDelimLint>::check_item(self, cx, item)
+    }
+}
 
-        if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind {
-            self.check_unused_parens_expr(cx, expr, "assigned value", false, None, None);
+declare_lint! {
+    pub(super) UNUSED_BRACES,
+    Warn,
+    "unnecessary braces around an expression"
+}
+
+declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
+
+impl UnusedDelimLint for UnusedBraces {
+    const DELIM_STR: &'static str = "braces";
+
+    fn lint(&self) -> &'static Lint {
+        UNUSED_BRACES
+    }
+
+    fn check_unused_delims_expr(
+        &self,
+        cx: &EarlyContext<'_>,
+        value: &ast::Expr,
+        ctx: UnusedDelimsCtx,
+        followed_by_block: bool,
+        left_pos: Option<BytePos>,
+        right_pos: Option<BytePos>,
+    ) {
+        match value.kind {
+            ast::ExprKind::Block(ref inner, None)
+                if inner.rules == ast::BlockCheckMode::Default =>
+            {
+                // emit a warning under the following conditions:
+                //
+                // - the block does not have a label
+                // - the block is not `unsafe`
+                // - the block contains exactly one expression (do not lint `{ expr; }`)
+                // - `followed_by_block` is true and the internal expr may contain a `{`
+                // - the block is not multiline (do not lint multiline match arms)
+                //      ```
+                //      match expr {
+                //          Pattern => {
+                //              somewhat_long_expression
+                //          }
+                //          // ...
+                //      }
+                //      ```
+                // - the block has no attribute and was not created inside a macro
+                // - if the block is an `anon_const`, the inner expr must be a literal
+                //      (do not lint `struct A<const N: usize>; let _: A<{ 2 + 3 }>;`)
+                //
+                // FIXME(const_generics): handle paths when #67075 is fixed.
+                if let [stmt] = inner.stmts.as_slice() {
+                    if let ast::StmtKind::Expr(ref expr) = stmt.kind {
+                        if !Self::is_expr_delims_necessary(expr, followed_by_block)
+                            && (ctx != UnusedDelimsCtx::AnonConst
+                                || matches!(expr.kind, ast::ExprKind::Lit(_)))
+                            // array length expressions are checked during `check_anon_const` and `check_ty`,
+                            // once as `ArrayLenExpr` and once as `AnonConst`.
+                            //
+                            // As we do not want to lint this twice, we do not emit an error for
+                            // `ArrayLenExpr` if `AnonConst` would do the same.
+                            && (ctx != UnusedDelimsCtx::ArrayLenExpr
+                                || !matches!(expr.kind, ast::ExprKind::Lit(_)))
+                            && !cx.sess().source_map().is_multiline(value.span)
+                            && value.attrs.is_empty()
+                            && !value.span.from_expansion()
+                        {
+                            self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
+                        }
+                    }
+                }
+            }
+            ast::ExprKind::Let(_, ref expr) => {
+                // FIXME(#60336): Properly handle `let true = (false && true)`
+                // actually needing the parenthesis.
+                self.check_unused_delims_expr(
+                    cx,
+                    expr,
+                    UnusedDelimsCtx::LetScrutineeExpr,
+                    followed_by_block,
+                    None,
+                    None,
+                );
+            }
+            _ => {}
+        }
+    }
+}
+
+impl EarlyLintPass for UnusedBraces {
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
+        <Self as UnusedDelimLint>::check_expr(self, cx, e)
+    }
+
+    fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) {
+        self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None);
+    }
+
+    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
+        <Self as UnusedDelimLint>::check_stmt(self, cx, s)
+    }
+
+    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
+        if let &ast::TyKind::Paren(ref r) = &ty.kind {
+            if let ast::TyKind::Array(_, ref len) = r.kind {
+                self.check_unused_delims_expr(
+                    cx,
+                    &len.value,
+                    UnusedDelimsCtx::ArrayLenExpr,
+                    false,
+                    None,
+                    None,
+                );
+            }
         }
     }
+
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
+        <Self as UnusedDelimLint>::check_item(self, cx, item)
+    }
 }
 
 declare_lint! {
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
index e7005f2f5ba77..33bcd9456c33b 100644
--- a/src/librustc_macros/src/query.rs
+++ b/src/librustc_macros/src/query.rs
@@ -356,9 +356,11 @@ fn add_query_description_impl(
                 quote! { #t }
             })
             .unwrap_or(quote! { _ });
+        // expr is a `Block`, meaning that `{ #expr }` gets expanded
+        // to `{ { stmts... } }`, which triggers the `unused_braces` lint.
         quote! {
             #[inline]
-            #[allow(unused_variables)]
+            #[allow(unused_variables, unused_braces)]
             fn cache_on_disk(
                 #tcx: TyCtxt<'tcx>,
                 #key: Self::Key,
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 9d5121cbad562..aba1567e6ef6b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2807,7 +2807,7 @@ impl<'a> Resolver<'a> {
             ast::Path {
                 span,
                 segments: iter::once(Ident::with_dummy_span(kw::PathRoot))
-                    .chain({ path_str.split("::").skip(1).map(Ident::from_str) })
+                    .chain(path_str.split("::").skip(1).map(Ident::from_str))
                     .map(|i| self.new_ast_path_segment(i))
                     .collect(),
             }
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index f2ad057b6b624..d00381792e351 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -115,8 +115,7 @@ impl RawHandle {
     ) -> io::Result<Option<usize>> {
         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
         let mut amt = 0;
-        let res =
-            cvt({ c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped) });
+        let res = cvt(c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped));
         match res {
             Ok(_) => Ok(Some(amt as usize)),
             Err(e) => {
@@ -139,7 +138,7 @@ impl RawHandle {
         unsafe {
             let mut bytes = 0;
             let wait = if wait { c::TRUE } else { c::FALSE };
-            let res = cvt({ c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait) });
+            let res = cvt(c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait));
             match res {
                 Ok(_) => Ok(bytes as usize),
                 Err(e) => {
diff --git a/src/test/incremental/const-generics/issue-61516.rs b/src/test/incremental/const-generics/issue-61516.rs
index a7465b77267a5..a193bf998dc73 100644
--- a/src/test/incremental/const-generics/issue-61516.rs
+++ b/src/test/incremental/const-generics/issue-61516.rs
@@ -4,7 +4,7 @@
 
 struct FakeArray<T, const N: usize>(T);
 
-impl<T, const N: usize> FakeArray<T, { N }> {
+impl<T, const N: usize> FakeArray<T, N> {
     fn len(&self) -> usize {
         N
     }
diff --git a/src/test/ui/array-slice-vec/vec-fixed-length.rs b/src/test/ui/array-slice-vec/vec-fixed-length.rs
index 5db02ee066bbe..908c39c7951c0 100644
--- a/src/test/ui/array-slice-vec/vec-fixed-length.rs
+++ b/src/test/ui/array-slice-vec/vec-fixed-length.rs
@@ -9,7 +9,7 @@ fn test_big_vec() {}
 #[cfg(target_pointer_width = "64")]
 fn test_big_vec()
 {
-    assert_eq!(size_of::<[u8; (1 << 32)]>(), (1 << 32));
+    assert_eq!(size_of::<[u8; 1 << 32]>(), (1 << 32));
 }
 
 fn main() {
diff --git a/src/test/ui/block-fn-coerce.rs b/src/test/ui/block-fn-coerce.rs
index fc5f51d46b255..d993ad9945974 100644
--- a/src/test/ui/block-fn-coerce.rs
+++ b/src/test/ui/block-fn-coerce.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 
 fn force<F>(f: F) -> isize where F: FnOnce() -> isize { return f(); }
 
diff --git a/src/test/ui/cleanup-rvalue-scopes.rs b/src/test/ui/cleanup-rvalue-scopes.rs
index f51f13abf792f..c5dd87c0f5a1f 100644
--- a/src/test/ui/cleanup-rvalue-scopes.rs
+++ b/src/test/ui/cleanup-rvalue-scopes.rs
@@ -1,5 +1,5 @@
 // run-pass
-
+#![allow(unused_braces)]
 #![allow(non_snake_case)]
 #![allow(unused_variables)]
 // Test that destructors for rvalue temporaries run either at end of
diff --git a/src/test/ui/coerce/coerce-expect-unsized.rs b/src/test/ui/coerce/coerce-expect-unsized.rs
index b44aa6ab37760..d486fdf73aba8 100644
--- a/src/test/ui/coerce/coerce-expect-unsized.rs
+++ b/src/test/ui/coerce/coerce-expect-unsized.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 #![feature(box_syntax)]
 
 use std::cell::RefCell;
diff --git a/src/test/ui/coerce/coerce-overloaded-autoderef.rs b/src/test/ui/coerce/coerce-overloaded-autoderef.rs
index 3fe18103ef8c3..d5484607c8b52 100644
--- a/src/test/ui/coerce/coerce-overloaded-autoderef.rs
+++ b/src/test/ui/coerce/coerce-overloaded-autoderef.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs
index cd3cfaac3b95b..212e16253f6b8 100644
--- a/src/test/ui/const-generics/issues/issue-62504.rs
+++ b/src/test/ui/const-generics/issues/issue-62504.rs
@@ -7,13 +7,13 @@ trait HasSize {
     const SIZE: usize;
 }
 
-impl<const X: usize> HasSize for ArrayHolder<{ X }> {
+impl<const X: usize> HasSize for ArrayHolder<X> {
     const SIZE: usize = X;
 }
 
 struct ArrayHolder<const X: usize>([u32; X]);
 
-impl<const X: usize> ArrayHolder<{ X }> {
+impl<const X: usize> ArrayHolder<X> {
     pub const fn new() -> Self {
         ArrayHolder([0; Self::SIZE])
         //~^ ERROR: mismatched types
diff --git a/src/test/ui/const-generics/issues/issue-70125-2.rs b/src/test/ui/const-generics/issues/issue-70125-2.rs
index ea7a68c2f93d9..a3eca0dd7d965 100644
--- a/src/test/ui/const-generics/issues/issue-70125-2.rs
+++ b/src/test/ui/const-generics/issues/issue-70125-2.rs
@@ -13,4 +13,4 @@ trait Foo<const X: usize> {
     }
 }
 
-impl Foo<{3}> for () {}
+impl Foo<3> for () {}
diff --git a/src/test/ui/const-generics/unused_braces.rs b/src/test/ui/const-generics/unused_braces.rs
new file mode 100644
index 0000000000000..05234faf71420
--- /dev/null
+++ b/src/test/ui/const-generics/unused_braces.rs
@@ -0,0 +1,13 @@
+// check-pass
+#![warn(unused_braces)]
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct A<const N: usize>;
+
+fn main() {
+    let _: A<7>; // ok
+    let _: A<{ 7 }>; //~ WARN unnecessary braces
+    let _: A<{ 3 + 5 }>; // ok
+}
diff --git a/src/test/ui/const-generics/unused_braces.stderr b/src/test/ui/const-generics/unused_braces.stderr
new file mode 100644
index 0000000000000..fc3da6096e7d4
--- /dev/null
+++ b/src/test/ui/const-generics/unused_braces.stderr
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/unused_braces.rs:4:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: unnecessary braces around const expression
+  --> $DIR/unused_braces.rs:11:14
+   |
+LL |     let _: A<{ 7 }>;
+   |              ^^^^^ help: remove these braces
+   |
+note: the lint level is defined here
+  --> $DIR/unused_braces.rs:2:9
+   |
+LL | #![warn(unused_braces)]
+   |         ^^^^^^^^^^^^^
+
diff --git a/src/test/ui/consts/const-block.rs b/src/test/ui/consts/const-block.rs
index 7172a34c8cfeb..ec99c70f6e0b9 100644
--- a/src/test/ui/consts/const-block.rs
+++ b/src/test/ui/consts/const-block.rs
@@ -1,5 +1,5 @@
 // run-pass
-
+#![allow(unused_braces)]
 #![allow(dead_code)]
 #![allow(unused_unsafe)]
 
diff --git a/src/test/ui/expr-block-generic-unique1.rs b/src/test/ui/expr-block-generic-unique1.rs
index c14191f2ffcb5..d081cb2be7ee3 100644
--- a/src/test/ui/expr-block-generic-unique1.rs
+++ b/src/test/ui/expr-block-generic-unique1.rs
@@ -1,5 +1,5 @@
 // run-pass
-
+#![allow(unused_braces)]
 #![feature(box_syntax)]
 
 fn test_generic<T, F>(expected: Box<T>, eq: F) where T: Clone, F: FnOnce(Box<T>, Box<T>) -> bool {
diff --git a/src/test/ui/expr-block-generic-unique2.rs b/src/test/ui/expr-block-generic-unique2.rs
index 90ebc02931ad1..9362eb86fc309 100644
--- a/src/test/ui/expr-block-generic-unique2.rs
+++ b/src/test/ui/expr-block-generic-unique2.rs
@@ -1,5 +1,5 @@
 // run-pass
-
+#![allow(unused_braces)]
 #![feature(box_syntax)]
 
 fn test_generic<T, F>(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> bool {
diff --git a/src/test/ui/expr-block-generic.rs b/src/test/ui/expr-block-generic.rs
index ec93f59722d0c..29c7c42219c73 100644
--- a/src/test/ui/expr-block-generic.rs
+++ b/src/test/ui/expr-block-generic.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 
 fn test_generic<T: Clone, F>(expected: T, eq: F) where F: FnOnce(T, T) -> bool {
     let actual: T = { expected.clone() };
diff --git a/src/test/ui/expr-block-unique.rs b/src/test/ui/expr-block-unique.rs
index fe1a7d9f1fb31..eff3fd3a15152 100644
--- a/src/test/ui/expr-block-unique.rs
+++ b/src/test/ui/expr-block-unique.rs
@@ -1,5 +1,5 @@
 // run-pass
-
+#![allow(unused_braces)]
 #![feature(box_syntax)]
 
 pub fn main() { let x: Box<_> = { box 100 }; assert_eq!(*x, 100); }
diff --git a/src/test/ui/expr-block.rs b/src/test/ui/expr-block.rs
index 549ccf9774f43..ff87595c934e9 100644
--- a/src/test/ui/expr-block.rs
+++ b/src/test/ui/expr-block.rs
@@ -1,10 +1,7 @@
 // run-pass
-
+#![allow(unused_braces)]
 #![allow(dead_code)]
 
-
-
-
 // Tests for standalone blocks as expressions
 
 fn test_basic() { let rs: bool = { true }; assert!((rs)); }
diff --git a/src/test/ui/expr-fn.rs b/src/test/ui/expr-fn.rs
index af809f563fc04..253cbfd5d38fa 100644
--- a/src/test/ui/expr-fn.rs
+++ b/src/test/ui/expr-fn.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 
 fn test_int() {
     fn f() -> isize { 10 }
diff --git a/src/test/ui/functions-closures/closure-inference.rs b/src/test/ui/functions-closures/closure-inference.rs
index 96878445245bc..1877414f09942 100644
--- a/src/test/ui/functions-closures/closure-inference.rs
+++ b/src/test/ui/functions-closures/closure-inference.rs
@@ -1,5 +1,5 @@
 // run-pass
-
+#![allow(unused_braces)]
 
 fn foo(i: isize) -> isize { i + 1 }
 
diff --git a/src/test/ui/functions-closures/closure-inference2.rs b/src/test/ui/functions-closures/closure-inference2.rs
index f2dfa5888aac5..4ce132e86caa4 100644
--- a/src/test/ui/functions-closures/closure-inference2.rs
+++ b/src/test/ui/functions-closures/closure-inference2.rs
@@ -1,6 +1,6 @@
 // run-pass
 // Test a rather underspecified example:
-
+#![allow(unused_braces)]
 
 pub fn main() {
     let f = {|i| i};
diff --git a/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs b/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs
index a2068429af5ea..9804c421db081 100644
--- a/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs
+++ b/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 #![allow(unused_unsafe)]
 #![allow(unreachable_code)]
 // ignore-emscripten no threads support
diff --git a/src/test/ui/issues/issue-23898.rs b/src/test/ui/issues/issue-23898.rs
index a8787f279b71b..3de365675ad22 100644
--- a/src/test/ui/issues/issue-23898.rs
+++ b/src/test/ui/issues/issue-23898.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_parens)]
 #![allow(non_camel_case_types)]
 
 // Note: This test was used to demonstrate #5873 (now #23898).
diff --git a/src/test/ui/issues/issue-28777.rs b/src/test/ui/issues/issue-28777.rs
index 74de00adadbda..1f426b7185e8f 100644
--- a/src/test/ui/issues/issue-28777.rs
+++ b/src/test/ui/issues/issue-28777.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 fn main() {
     let v1 = { 1 + {2} * {3} };
     let v2 =   1 + {2} * {3}  ;
diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs
index 5ce1f57608132..623cd04d9bce3 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.rs
+++ b/src/test/ui/lint/lint-unnecessary-parens.rs
@@ -48,11 +48,11 @@ fn main() {
     if (true) {} //~ ERROR unnecessary parentheses around `if` condition
     while (true) {} //~ ERROR unnecessary parentheses around `while` condition
     //~^ WARN denote infinite loops with
-    match (true) { //~ ERROR unnecessary parentheses around `match` head expression
+    match (true) { //~ ERROR unnecessary parentheses around `match` scrutinee expression
         _ => {}
     }
-    if let 1 = (1) {} //~ ERROR unnecessary parentheses around `let` head expression
-    while let 1 = (2) {} //~ ERROR unnecessary parentheses around `let` head expression
+    if let 1 = (1) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression
+    while let 1 = (2) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression
     let v = X { y: false };
     // struct lits needs parens, so these shouldn't warn.
     if (v == X { y: true }) {}
diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr
index 8858c95327322..15184ba36ae85 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.stderr
+++ b/src/test/ui/lint/lint-unnecessary-parens.stderr
@@ -72,19 +72,19 @@ LL |     while (true) {}
    |
    = note: `#[warn(while_true)]` on by default
 
-error: unnecessary parentheses around `match` head expression
+error: unnecessary parentheses around `match` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:51:11
    |
 LL |     match (true) {
    |           ^^^^^^ help: remove these parentheses
 
-error: unnecessary parentheses around `let` head expression
+error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:54:16
    |
 LL |     if let 1 = (1) {}
    |                ^^^ help: remove these parentheses
 
-error: unnecessary parentheses around `let` head expression
+error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:55:19
    |
 LL |     while let 1 = (2) {}
diff --git a/src/test/ui/lint/unused_braces.rs b/src/test/ui/lint/unused_braces.rs
new file mode 100644
index 0000000000000..de456ee6c230c
--- /dev/null
+++ b/src/test/ui/lint/unused_braces.rs
@@ -0,0 +1,31 @@
+// check-pass
+#![warn(unused_braces, unused_parens)]
+
+fn main() {
+    let _ = (7);
+    //~^WARN unnecessary parentheses
+
+    let _ = { 7 };
+    //~^ WARN unnecessary braces
+
+    if let 7 = { 7 } {
+        //~^ WARN unnecessary braces
+    }
+
+    let _: [u8; { 3 }];
+    //~^ WARN unnecessary braces
+
+    // do not emit error for multiline blocks.
+    let _ = {
+        7
+    };
+
+    // do not emit error for unsafe blocks.
+    let _ = unsafe { 7 };
+
+    // do not emit error, as the `{` would then
+    // be parsed as part of the `return`.
+    if { return } {
+
+    }
+}
diff --git a/src/test/ui/lint/unused_braces.stderr b/src/test/ui/lint/unused_braces.stderr
new file mode 100644
index 0000000000000..72f425ffc3e01
--- /dev/null
+++ b/src/test/ui/lint/unused_braces.stderr
@@ -0,0 +1,36 @@
+warning: unnecessary parentheses around assigned value
+  --> $DIR/unused_braces.rs:5:13
+   |
+LL |     let _ = (7);
+   |             ^^^ help: remove these parentheses
+   |
+note: the lint level is defined here
+  --> $DIR/unused_braces.rs:2:24
+   |
+LL | #![warn(unused_braces, unused_parens)]
+   |                        ^^^^^^^^^^^^^
+
+warning: unnecessary braces around assigned value
+  --> $DIR/unused_braces.rs:8:13
+   |
+LL |     let _ = { 7 };
+   |             ^^^^^ help: remove these braces
+   |
+note: the lint level is defined here
+  --> $DIR/unused_braces.rs:2:9
+   |
+LL | #![warn(unused_braces, unused_parens)]
+   |         ^^^^^^^^^^^^^
+
+warning: unnecessary braces around `let` scrutinee expression
+  --> $DIR/unused_braces.rs:11:16
+   |
+LL |     if let 7 = { 7 } {
+   |                ^^^^^ help: remove these braces
+
+warning: unnecessary braces around const expression
+  --> $DIR/unused_braces.rs:15:17
+   |
+LL |     let _: [u8; { 3 }];
+   |                 ^^^^^ help: remove these braces
+
diff --git a/src/test/ui/lint/unused_parens_borrow.rs b/src/test/ui/lint/unused_parens_borrow.rs
new file mode 100644
index 0000000000000..98dbbecfedde6
--- /dev/null
+++ b/src/test/ui/lint/unused_parens_borrow.rs
@@ -0,0 +1,22 @@
+// check-pass
+#![warn(unused_braces)]
+
+// changing `&{ expr }` to `&expr` changes the semantic of the program
+// so we should not warn this case
+
+#[repr(packed)]
+struct A {
+    a: u8,
+    b: u32,
+}
+
+fn main() {
+    let a = A {
+        a: 42,
+        b: 1729,
+    };
+
+    let _ = &{ a.b };
+    let _ = { a.b };
+    //~^ WARN unnecessary braces
+}
diff --git a/src/test/ui/lint/unused_parens_borrow.stderr b/src/test/ui/lint/unused_parens_borrow.stderr
new file mode 100644
index 0000000000000..7e3839ae4e014
--- /dev/null
+++ b/src/test/ui/lint/unused_parens_borrow.stderr
@@ -0,0 +1,12 @@
+warning: unnecessary braces around assigned value
+  --> $DIR/unused_parens_borrow.rs:20:13
+   |
+LL |     let _ = { a.b };
+   |             ^^^^^^^ help: remove these braces
+   |
+note: the lint level is defined here
+  --> $DIR/unused_parens_borrow.rs:2:9
+   |
+LL | #![warn(unused_braces)]
+   |         ^^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
index c3bf77a3a6f2d..5fb67fd7c95a3 100644
--- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
@@ -46,14 +46,14 @@ LL |     while(true && false) {
    |          ^^^^^^^^^^^^^^^ help: remove these parentheses
 
 "}
-{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
   --> $DIR/unused_parens_remove_json_suggestion.rs:44:18
    |
 LL |         for _ in (0 .. 3){
    |                  ^^^^^^^^ help: remove these parentheses
 
 "}
-{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:49:14
    |
 LL |     for _ in (0 .. 3) {
diff --git a/src/test/ui/range.rs b/src/test/ui/range.rs
index 82983e37ea18e..f3f7508d12434 100644
--- a/src/test/ui/range.rs
+++ b/src/test/ui/range.rs
@@ -1,5 +1,5 @@
 // run-pass
-
+#![allow(unused_braces)]
 #![allow(unused_comparisons)]
 #![allow(dead_code)]
 #![allow(unused_mut)]
diff --git a/src/test/ui/range_inclusive.rs b/src/test/ui/range_inclusive.rs
index 68d9bf7d26b69..540b35e0392de 100644
--- a/src/test/ui/range_inclusive.rs
+++ b/src/test/ui/range_inclusive.rs
@@ -1,7 +1,7 @@
 // run-pass
 // Test inclusive range syntax.
-
 #![feature(range_is_empty)]
+#![allow(unused_braces)]
 #![allow(unused_comparisons)]
 
 use std::ops::RangeToInclusive;
diff --git a/src/test/ui/structs-enums/empty-tag.rs b/src/test/ui/structs-enums/empty-tag.rs
index 56a438200c00b..271ab72c74fc1 100644
--- a/src/test/ui/structs-enums/empty-tag.rs
+++ b/src/test/ui/structs-enums/empty-tag.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 #![allow(non_camel_case_types)]
 
 #[derive(Copy, Clone, Debug)]
diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs
index 2907c21c6203c..7f3f86e4df009 100644
--- a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs
+++ b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs
@@ -18,16 +18,16 @@ trait MyTrait<'a, const C: usize> {
     const MY_CONST: usize;
 }
 
-impl<'a, const C: usize> MyTrait<'a, { C }> for MyStruct<{ C }> {
+impl<'a, const C: usize> MyTrait<'a, C> for MyStruct<C> {
     type MyItem = u8;
     const MY_CONST: usize = C;
 }
 
-impl<'a, I, const C: usize> UnwrapItemsExt<'a, { C }> for I {
-    type Iter = impl MyTrait<'a, { C }>;
+impl<'a, I, const C: usize> UnwrapItemsExt<'a, C> for I {
+    type Iter = impl MyTrait<'a, C>;
 
     fn unwrap_items(self) -> Self::Iter {
-        MyStruct::<{ C }> {}
+        MyStruct::<C> {}
     }
 }
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
index bc64fcdec2e39..24c2758a0a255 100644
--- a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
@@ -1,5 +1,5 @@
 // run-pass
-
+#![allow(unused_braces, unused_parens)]
 #![feature(unsized_tuple_coercion, unsized_locals)]
 
 struct A<X: ?Sized>(X);
@@ -30,7 +30,6 @@ fn main() {
         *foo()
     });
     udrop::<[u8]>({*foo()});
-    #[allow(unused_parens)]
     udrop::<[u8]>((*foo()));
     udrop::<[u8]>((*tfoo()).1);
     *afoo() + 42;
diff --git a/src/test/ui/weird-exprs.rs b/src/test/ui/weird-exprs.rs
index ca68a5af0ddca..d812bbd011e0e 100644
--- a/src/test/ui/weird-exprs.rs
+++ b/src/test/ui/weird-exprs.rs
@@ -5,7 +5,7 @@
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
 #![allow(unreachable_code)]
-#![allow(unused_parens)]
+#![allow(unused_braces, unused_parens)]
 
 #![recursion_limit = "256"]
 
diff --git a/src/test/ui/zero-sized/zero-sized-tuple-struct.rs b/src/test/ui/zero-sized/zero-sized-tuple-struct.rs
index 6c438720e5d86..2208590f7d61b 100644
--- a/src/test/ui/zero-sized/zero-sized-tuple-struct.rs
+++ b/src/test/ui/zero-sized/zero-sized-tuple-struct.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_braces)]
 #![allow(unused_assignments)]
 
 // Make sure that the constructor args are codegened for zero-sized tuple structs