about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-09-29 18:35:04 +0000
committerbors <bors@rust-lang.org>2019-09-29 18:35:04 +0000
commit8431f261dd160021b6af85916f161a13dd101ca0 (patch)
tree73c411884bf616dec9f4efa6ef66ee2275358205
parent06c68947ad88f22a8342fe6b54dc0fe54de6e011 (diff)
parent50940ae952ffcab9abd39a2bc1dfd3e1605e0ece (diff)
downloadrust-8431f261dd160021b6af85916f161a13dd101ca0.tar.gz
rust-8431f261dd160021b6af85916f161a13dd101ca0.zip
Auto merge of #64902 - Centril:rollup-1i431vs, r=Centril
Rollup of 6 pull requests

Successful merges:

 - #64691 (Point at definition when misusing ADT)
 - #64735 (Add long error explanation for E0533)
 - #64825 (Point at enclosing match when expecting `()` in arm)
 - #64858 (Add support for relating slices in `super_relate_consts`)
 - #64894 (syntax: fix dropping of attribute on first param of non-method assocated fn)
 - #64898 (fixed typo)

Failed merges:

r? @ghost
-rw-r--r--README.md2
-rw-r--r--src/librustc/hir/lowering/expr.rs23
-rw-r--r--src/librustc/hir/map/mod.rs26
-rw-r--r--src/librustc/mir/interpret/mod.rs2
-rw-r--r--src/librustc/mir/interpret/value.rs15
-rw-r--r--src/librustc/ty/relate.rs17
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs29
-rw-r--r--src/librustc_resolve/late/diagnostics.rs22
-rw-r--r--src/librustc_typeck/check/_match.rs8
-rw-r--r--src/librustc_typeck/check/coercion.rs73
-rw-r--r--src/librustc_typeck/check/expr.rs9
-rw-r--r--src/librustc_typeck/check/mod.rs14
-rw-r--r--src/librustc_typeck/error_codes.rs38
-rw-r--r--src/libsyntax/parse/parser.rs73
-rw-r--r--src/libsyntax/parse/parser/item.rs44
-rw-r--r--src/test/ui/const-generics/slice-const-param-mismatch.rs14
-rw-r--r--src/test/ui/const-generics/slice-const-param-mismatch.stderr38
-rw-r--r--src/test/ui/const-generics/slice-const-param.rs19
-rw-r--r--src/test/ui/const-generics/slice-const-param.stderr8
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr12
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-1.stderr3
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-2.stderr6
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-3.stderr6
-rw-r--r--src/test/ui/empty/empty-struct-tuple-pat.stderr7
-rw-r--r--src/test/ui/error-codes/E0423.stderr3
-rw-r--r--src/test/ui/issues/issue-19086.stderr3
-rw-r--r--src/test/ui/issues/issue-32004.stderr5
-rw-r--r--src/test/ui/issues/issue-63983.stderr8
-rw-r--r--src/test/ui/lint/lint-unused-variables.rs15
-rw-r--r--src/test/ui/lint/lint-unused-variables.stderr28
-rw-r--r--src/test/ui/methods/method-path-in-pattern.rs6
-rw-r--r--src/test/ui/methods/method-path-in-pattern.stderr21
-rw-r--r--src/test/ui/namespace/namespace-mix.stderr3
-rw-r--r--src/test/ui/parser/recover-from-bad-variant.stderr3
-rw-r--r--src/test/ui/qualified/qualified-path-params.stderr3
-rw-r--r--src/test/ui/resolve/issue-18252.stderr3
-rw-r--r--src/test/ui/resolve/issue-19452.stderr3
-rw-r--r--src/test/ui/resolve/issue-39226.stderr3
-rw-r--r--src/test/ui/resolve/issue-6702.stderr9
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr36
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr9
-rw-r--r--src/test/ui/rfc-2565-param-attrs/attr-without-param.rs16
-rw-r--r--src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr20
-rw-r--r--src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs12
-rw-r--r--src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs21
-rw-r--r--src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs31
-rw-r--r--src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr126
-rw-r--r--src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs24
-rw-r--r--src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr52
-rw-r--r--src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs6
-rw-r--r--src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs6
-rw-r--r--src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr44
-rw-r--r--src/test/ui/struct-literal-variant-in-if.stderr5
-rw-r--r--src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr3
-rw-r--r--src/test/ui/suggestions/issue-61226.stderr3
-rw-r--r--src/test/ui/suggestions/match-needing-semi.fixed18
-rw-r--r--src/test/ui/suggestions/match-needing-semi.rs18
-rw-r--r--src/test/ui/suggestions/match-needing-semi.stderr36
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr1
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr2
60 files changed, 881 insertions, 232 deletions
diff --git a/README.md b/README.md
index 495ee46a9ac..9462b10494c 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ or reading the [rustc guide][rustcguidebuild].
    * `curl`
    * `git`
    * `ssl` which comes in `libssl-dev` or `openssl-devel`
-   * `pkg-config` if you are on compiling on Linux and targeting Linux
+   * `pkg-config` if you are compiling on Linux and targeting Linux
 
 2. Clone the [source] with `git`:
 
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index 2f0a318d536..9dcecedd97c 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -1037,10 +1037,9 @@ impl LoweringContext<'_> {
     ) -> hir::Expr {
         // expand <head>
         let mut head = self.lower_expr(head);
-        let head_sp = head.span;
         let desugared_span = self.mark_span_with_reason(
             DesugaringKind::ForLoop,
-            head_sp,
+            head.span,
             None,
         );
         head.span = desugared_span;
@@ -1086,21 +1085,21 @@ impl LoweringContext<'_> {
 
         // `match ::std::iter::Iterator::next(&mut iter) { ... }`
         let match_expr = {
-            let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid));
-            let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter);
+            let iter = P(self.expr_ident(desugared_span, iter, iter_pat_nid));
+            let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
             let next_path = &[sym::iter, sym::Iterator, sym::next];
             let next_expr = P(self.expr_call_std_path(
-                head_sp,
+                desugared_span,
                 next_path,
                 hir_vec![ref_mut_iter],
             ));
             let arms = hir_vec![pat_arm, break_arm];
 
-            self.expr_match(head_sp, next_expr, arms, hir::MatchSource::ForLoopDesugar)
+            self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
         };
-        let match_stmt = self.stmt_expr(head_sp, match_expr);
+        let match_stmt = self.stmt_expr(desugared_span, match_expr);
 
-        let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid));
+        let next_expr = P(self.expr_ident(desugared_span, next_ident, next_pat_hid));
 
         // `let mut __next`
         let next_let = self.stmt_let_pat(
@@ -1115,7 +1114,7 @@ impl LoweringContext<'_> {
         let pat = self.lower_pat(pat);
         let pat_let = self.stmt_let_pat(
             ThinVec::new(),
-            head_sp,
+            desugared_span,
             Some(next_expr),
             pat,
             hir::LocalSource::ForLoopDesugar,
@@ -1152,14 +1151,14 @@ impl LoweringContext<'_> {
             let into_iter_path =
                 &[sym::iter, sym::IntoIterator, sym::into_iter];
             P(self.expr_call_std_path(
-                head_sp,
+                desugared_span,
                 into_iter_path,
                 hir_vec![head],
             ))
         };
 
         let match_expr = P(self.expr_match(
-            head_sp,
+            desugared_span,
             into_iter_expr,
             hir_vec![iter_arm],
             hir::MatchSource::ForLoopDesugar,
@@ -1171,7 +1170,7 @@ impl LoweringContext<'_> {
         // surrounding scope of the `match` since the `match` is not a terminating scope.
         //
         // Also, add the attributes to the outer returned expr node.
-        self.expr_drop_temps(head_sp, match_expr, e.attrs.clone())
+        self.expr_drop_temps(desugared_span, match_expr, e.attrs.clone())
     }
 
     /// Desugar `ExprKind::Try` from: `<expr>?` into:
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 42a4a9909f8..a1011697ef1 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -818,6 +818,32 @@ impl<'hir> Map<'hir> {
         CRATE_HIR_ID
     }
 
+    /// When on a match arm tail expression or on a match arm, give back the enclosing `match`
+    /// expression.
+    ///
+    /// Used by error reporting when there's a type error in a match arm caused by the `match`
+    /// expression needing to be unit.
+    pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&Expr> {
+        for (_, node) in ParentHirIterator::new(hir_id, &self) {
+            match node {
+                Node::Item(_) |
+                Node::ForeignItem(_) |
+                Node::TraitItem(_) |
+                Node::ImplItem(_) => break,
+                Node::Expr(expr) => match expr.kind {
+                    ExprKind::Match(_, _, _) => return Some(expr),
+                    _ => {}
+                },
+                Node::Stmt(stmt) => match stmt.kind {
+                    StmtKind::Local(_) => break,
+                    _ => {}
+                }
+                _ => {}
+            }
+        }
+        None
+    }
+
     /// Returns the nearest enclosing scope. A scope is roughly an item or block.
     pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> {
         for (hir_id, node) in ParentHirIterator::new(hir_id, &self) {
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index cd58396d95c..e925d7429ff 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -101,7 +101,7 @@ pub use self::error::{
     InvalidProgramInfo, ResourceExhaustionInfo, UndefinedBehaviorInfo,
 };
 
-pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};
+pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue, get_slice_bytes};
 
 pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask};
 
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index b8bc7414197..32f45cd9d47 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -611,3 +611,18 @@ impl_stable_hash_for!(enum crate::mir::interpret::ScalarMaybeUndef {
     Scalar(v),
     Undef
 });
+
+/// Gets the bytes of a constant slice value.
+pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] {
+    if let ConstValue::Slice { data, start, end } = val {
+        let len = end - start;
+        data.get_bytes(
+            cx,
+            // invent a pointer, only the offset is relevant anyway
+            Pointer::new(AllocId(0), Size::from_bytes(start as u64)),
+            Size::from_bytes(len as u64),
+        ).unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err))
+    } else {
+        bug!("expected const slice, but found another const value");
+    }
+}
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 2af6963f712..3bd61e34554 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
 use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use crate::ty::error::{ExpectedFound, TypeError};
-use crate::mir::interpret::{ConstValue, Scalar};
+use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar};
 use std::rc::Rc;
 use std::iter;
 use rustc_target::spec::abi;
@@ -584,7 +584,20 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
         // FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment
         // saying that we're not handling it intentionally.
 
-        // FIXME(const_generics): handle `ConstValue::ByRef` and `ConstValue::Slice`.
+        (a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => {
+            let a_bytes = get_slice_bytes(&tcx, a_val);
+            let b_bytes = get_slice_bytes(&tcx, b_val);
+            if a_bytes == b_bytes {
+                Ok(tcx.mk_const(ty::Const {
+                    val: a_val,
+                    ty: a.ty,
+                }))
+            } else {
+                Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+            }
+        }
+
+        // FIXME(const_generics): handle `ConstValue::ByRef`.
 
         // FIXME(const_generics): this is wrong, as it is a projection
         (ConstValue::Unevaluated(a_def_id, a_substs),
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 4d2fee3d160..fcdf2719ab6 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -13,12 +13,12 @@ use crate::hair::constant::*;
 use rustc::lint;
 use rustc::mir::{Field, BorrowKind, Mutability};
 use rustc::mir::{UserTypeProjection};
-use rustc::mir::interpret::{GlobalId, ConstValue, sign_extend, AllocId, Pointer};
+use rustc::mir::interpret::{GlobalId, ConstValue, get_slice_bytes, sign_extend};
 use rustc::traits::{ObligationCause, PredicateObligation};
 use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
 use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
 use rustc::ty::subst::{SubstsRef, GenericArg};
-use rustc::ty::layout::{VariantIdx, Size};
+use rustc::ty::layout::VariantIdx;
 use rustc::hir::{self, RangeEnd};
 use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -1526,27 +1526,10 @@ pub fn compare_const_vals<'tcx>(
 
     if let ty::Str = ty.kind {
         match (a.val, b.val) {
-            (
-                ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a },
-                ConstValue::Slice { data: alloc_b, start: offset_b, end: end_b },
-            ) => {
-                let len_a = end_a - offset_a;
-                let len_b = end_b - offset_b;
-                let a = alloc_a.get_bytes(
-                    &tcx,
-                    // invent a pointer, only the offset is relevant anyway
-                    Pointer::new(AllocId(0), Size::from_bytes(offset_a as u64)),
-                    Size::from_bytes(len_a as u64),
-                );
-                let b = alloc_b.get_bytes(
-                    &tcx,
-                    // invent a pointer, only the offset is relevant anyway
-                    Pointer::new(AllocId(0), Size::from_bytes(offset_b as u64)),
-                    Size::from_bytes(len_b as u64),
-                );
-                if let (Ok(a), Ok(b)) = (a, b) {
-                    return from_bool(a == b);
-                }
+            (ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
+                let a_bytes = get_slice_bytes(&tcx, a.val);
+                let b_bytes = get_slice_bytes(&tcx, b.val);
+                return from_bool(a_bytes == b_bytes);
             }
             _ => (),
         }
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 0d35cc53ac6..d3bf82b66ad 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -348,7 +348,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
             _ => false,
         };
 
-        let mut bad_struct_syntax_suggestion = || {
+        let mut bad_struct_syntax_suggestion = |def_id: DefId| {
             let (followed_by_brace, closing_brace) = self.followed_by_brace(span);
             let mut suggested = false;
             match source {
@@ -374,6 +374,9 @@ impl<'a> LateResolutionVisitor<'a, '_> {
                 _ => {}
             }
             if !suggested {
+                if let Some(span) = self.r.definitions.opt_span(def_id) {
+                    err.span_label(span, &format!("`{}` defined here", path_str));
+                }
                 err.span_label(
                     span,
                     format!("did you mean `{} {{ /* fields */ }}`?", path_str),
@@ -437,18 +440,21 @@ impl<'a> LateResolutionVisitor<'a, '_> {
                         );
                     }
                 } else {
-                    bad_struct_syntax_suggestion();
+                    bad_struct_syntax_suggestion(def_id);
                 }
             }
-            (Res::Def(DefKind::Union, _), _) |
-            (Res::Def(DefKind::Variant, _), _) |
-            (Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _), _) if ns == ValueNS => {
-                bad_struct_syntax_suggestion();
+            (Res::Def(DefKind::Union, def_id), _) |
+            (Res::Def(DefKind::Variant, def_id), _) |
+            (Res::Def(DefKind::Ctor(_, CtorKind::Fictive), def_id), _) if ns == ValueNS => {
+                bad_struct_syntax_suggestion(def_id);
             }
-            (Res::Def(DefKind::Ctor(_, CtorKind::Fn), _), _) if ns == ValueNS => {
+            (Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => {
+                if let Some(span) = self.r.definitions.opt_span(def_id) {
+                    err.span_label(span, &format!("`{}` defined here", path_str));
+                }
                 err.span_label(
                     span,
-                    format!("did you mean `{} ( /* fields */ )`?", path_str),
+                    format!("did you mean `{}( /* fields */ )`?", path_str),
                 );
             }
             (Res::SelfTy(..), _) if ns == ValueNS => {
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 13b6b1b8aa0..a1daed005f3 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -36,7 +36,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
             //
             // FIXME(60707): Consider removing hack with principled solution.
-            self.check_expr_has_type_or_error(discrim, self.tcx.types.bool)
+            self.check_expr_has_type_or_error(discrim, self.tcx.types.bool, |_| {})
         } else {
             self.demand_discriminant_type(arms, discrim)
         };
@@ -106,7 +106,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if let Some(g) = &arm.guard {
                 self.diverges.set(pats_diverge);
                 match g {
-                    hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
+                    hir::Guard::If(e) => {
+                        self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {})
+                    }
                 };
             }
 
@@ -442,7 +444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 kind: TypeVariableOriginKind::TypeInference,
                 span: discrim.span,
             });
-            self.check_expr_has_type_or_error(discrim, discrim_ty);
+            self.check_expr_has_type_or_error(discrim, discrim_ty, |_| {});
             discrim_ty
         }
     }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 564a0eac755..56962d53a64 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1163,18 +1163,20 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 fcx.try_coerce(expression, expression_ty, self.expected_ty, AllowTwoPhase::No)
             } else {
                 match self.expressions {
-                    Expressions::Dynamic(ref exprs) =>
-                        fcx.try_find_coercion_lub(cause,
-                                                  exprs,
-                                                  self.merged_ty(),
-                                                  expression,
-                                                  expression_ty),
-                    Expressions::UpFront(ref coercion_sites) =>
-                        fcx.try_find_coercion_lub(cause,
-                                                  &coercion_sites[0..self.pushed],
-                                                  self.merged_ty(),
-                                                  expression,
-                                                  expression_ty),
+                    Expressions::Dynamic(ref exprs) => fcx.try_find_coercion_lub(
+                        cause,
+                        exprs,
+                        self.merged_ty(),
+                        expression,
+                        expression_ty,
+                    ),
+                    Expressions::UpFront(ref coercion_sites) => fcx.try_find_coercion_lub(
+                        cause,
+                        &coercion_sites[0..self.pushed],
+                        self.merged_ty(),
+                        expression,
+                        expression_ty,
+                    ),
                 }
             }
         } else {
@@ -1216,7 +1218,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                     self.pushed += 1;
                 }
             }
-            Err(err) => {
+            Err(coercion_error) => {
                 let (expected, found) = if label_expression_as_expected {
                     // In the case where this is a "forced unit", like
                     // `break`, we want to call the `()` "expected"
@@ -1232,41 +1234,42 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                     (self.final_ty.unwrap_or(self.expected_ty), expression_ty)
                 };
 
-                let mut db;
+                let mut err;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
-                        db = struct_span_err!(
+                        err = struct_span_err!(
                             fcx.tcx.sess, cause.span, E0069,
                             "`return;` in a function whose return type is not `()`");
-                        db.span_label(cause.span, "return type is not `()`");
+                        err.span_label(cause.span, "return type is not `()`");
                     }
                     ObligationCauseCode::BlockTailExpression(blk_id) => {
                         let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
-                        db = self.report_return_mismatched_types(
+                        err = self.report_return_mismatched_types(
                             cause,
                             expected,
                             found,
-                            err,
+                            coercion_error,
                             fcx,
                             parent_id,
                             expression.map(|expr| (expr, blk_id)),
                         );
                     }
                     ObligationCauseCode::ReturnValue(id) => {
-                        db = self.report_return_mismatched_types(
-                            cause, expected, found, err, fcx, id, None);
+                        err = self.report_return_mismatched_types(
+                            cause, expected, found, coercion_error, fcx, id, None);
                     }
                     _ => {
-                        db = fcx.report_mismatched_types(cause, expected, found, err);
+                        err = fcx.report_mismatched_types(cause, expected, found, coercion_error);
                     }
                 }
 
                 if let Some(augment_error) = augment_error {
-                    augment_error(&mut db);
+                    augment_error(&mut err);
                 }
 
                 // Error possibly reported in `check_assign` so avoid emitting error again.
-                db.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected)).is_some());
+                err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected))
+                    .is_some());
 
                 self.final_ty = Some(fcx.tcx.types.err);
             }
@@ -1278,12 +1281,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         cause: &ObligationCause<'tcx>,
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
-        err: TypeError<'tcx>,
+        ty_err: TypeError<'tcx>,
         fcx: &FnCtxt<'a, 'tcx>,
         id: hir::HirId,
         expression: Option<(&'tcx hir::Expr, hir::HirId)>,
     ) -> DiagnosticBuilder<'a> {
-        let mut db = fcx.report_mismatched_types(cause, expected, found, err);
+        let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err);
 
         let mut pointing_at_return_type = false;
         let mut return_sp = None;
@@ -1294,7 +1297,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         let parent_id = fcx.tcx.hir().get_parent_node(id);
         let fn_decl = if let Some((expr, blk_id)) = expression {
             pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
-                &mut db,
+                &mut err,
                 expr,
                 expected,
                 found,
@@ -1302,6 +1305,16 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 blk_id,
             );
             let parent = fcx.tcx.hir().get(parent_id);
+            if let (Some(match_expr), true, false) = (
+                fcx.tcx.hir().get_match_if_cause(expr.hir_id),
+                expected.is_unit(),
+                pointing_at_return_type,
+            ) {
+                if match_expr.span.desugaring_kind().is_none() {
+                    err.span_label(match_expr.span, "expected this to be `()`");
+                    fcx.suggest_semicolon_at_end(match_expr.span, &mut err);
+                }
+            }
             fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
         } else {
             fcx.get_fn_decl(parent_id)
@@ -1310,20 +1323,20 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         if let (Some((fn_decl, can_suggest)), _) = (fn_decl, pointing_at_return_type) {
             if expression.is_none() {
                 pointing_at_return_type |= fcx.suggest_missing_return_type(
-                    &mut db, &fn_decl, expected, found, can_suggest);
+                    &mut err, &fn_decl, expected, found, can_suggest);
             }
             if !pointing_at_return_type {
                 return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
             }
         }
         if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
-            db.span_label(return_sp, "expected because this return type...");
-            db.span_label( *sp, format!(
+            err.span_label(return_sp, "expected because this return type...");
+            err.span_label( *sp, format!(
                 "...is found to be `{}` here",
                 fcx.resolve_type_vars_with_obligations(expected),
             ));
         }
-        db
+        err
     }
 
     pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 6bed321d27f..04c8536de8d 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -53,14 +53,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr: &'tcx hir::Expr,
         expected: Ty<'tcx>,
+        extend_err: impl Fn(&mut DiagnosticBuilder<'_>),
     ) -> Ty<'tcx> {
-        self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected))
+        self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected), extend_err)
     }
 
     fn check_expr_meets_expectation_or_error(
         &self,
         expr: &'tcx hir::Expr,
         expected: Expectation<'tcx>,
+        extend_err: impl Fn(&mut DiagnosticBuilder<'_>),
     ) -> Ty<'tcx> {
         let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool);
         let mut ty = self.check_expr_with_expectation(expr, expected);
@@ -88,6 +90,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ExprKind::DropTemps(expr) => expr,
                 _ => expr,
             };
+            extend_err(&mut err);
             // Error possibly reported in `check_assign` so avoid emitting error again.
             err.emit_unless(self.is_assign_to_bool(expr, expected_ty));
         }
@@ -971,7 +974,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: element.span,
                 });
-                let element_ty = self.check_expr_has_type_or_error(&element, ty);
+                let element_ty = self.check_expr_has_type_or_error(&element, ty, |_| {});
                 (element_ty, ty)
             }
         };
@@ -1058,7 +1061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // the fields with the base_expr. This could cause us to hit errors later
             // when certain fields are assumed to exist that in fact do not.
             if !error_happened {
-                self.check_expr_has_type_or_error(base_expr, adt_ty);
+                self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {});
                 match adt_ty.kind {
                     ty::Adt(adt, substs) if adt.is_struct() => {
                         let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a7832b8c2cf..092ab0936c0 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3879,6 +3879,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn suggest_semicolon_at_end(&self, span: Span, err: &mut DiagnosticBuilder<'_>) {
+        err.span_suggestion_short(
+            span.shrink_to_hi(),
+            "consider using a semicolon here",
+            ";".to_string(),
+            Applicability::MachineApplicable,
+        );
+    }
+
     pub fn check_stmt(&self, stmt: &'tcx hir::Stmt) {
         // Don't do all the complex logic below for `DeclItem`.
         match stmt.kind {
@@ -3902,7 +3911,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             hir::StmtKind::Item(_) => {}
             hir::StmtKind::Expr(ref expr) => {
                 // Check with expected type of `()`.
-                self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit());
+
+                self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| {
+                    self.suggest_semicolon_at_end(expr.span, err);
+                });
             }
             hir::StmtKind::Semi(ref expr) => {
                 self.check_expr(&expr);
diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs
index e11dcfafb8f..3a07171b12f 100644
--- a/src/librustc_typeck/error_codes.rs
+++ b/src/librustc_typeck/error_codes.rs
@@ -3610,6 +3610,43 @@ match r {
 ```
 "##,
 
+E0533: r##"
+An item which isn't a unit struct, a variant, nor a constant has been used as a
+match pattern.
+
+Erroneous code example:
+
+```compile_fail,E0533
+struct Tortoise;
+
+impl Tortoise {
+    fn turtle(&self) -> u32 { 0 }
+}
+
+match 0u32 {
+    Tortoise::turtle => {} // Error!
+    _ => {}
+}
+if let Tortoise::turtle = 0u32 {} // Same error!
+```
+
+If you want to match against a value returned by a method, you need to bind the
+value first:
+
+```
+struct Tortoise;
+
+impl Tortoise {
+    fn turtle(&self) -> u32 { 0 }
+}
+
+match 0u32 {
+    x if x == Tortoise.turtle() => {} // Bound into `x` then we compare it!
+    _ => {}
+}
+```
+"##,
+
 E0534: r##"
 The `inline` attribute was malformed.
 
@@ -4935,7 +4972,6 @@ and the pin is required to keep it in the same place in memory.
     E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with the same definition
 //  E0558, // replaced with a generic attribute input check
-    E0533, // `{}` does not name a unit variant, unit struct or a constant
 //  E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
     E0564, // only named lifetimes are allowed in `impl Trait`,
            // but `{}` was found in the type `{}`
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f22fd5ad703..2fb6f197dad 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -974,15 +974,22 @@ impl<'a> Parser<'a> {
     /// This version of parse param doesn't necessarily require identifier names.
     fn parse_param_general(
         &mut self,
+        is_self_allowed: bool,
         is_trait_item: bool,
         allow_c_variadic: bool,
         is_name_required: impl Fn(&token::Token) -> bool,
     ) -> PResult<'a, Param> {
         let lo = self.token.span;
         let attrs = self.parse_outer_attributes()?;
+
+        // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
         if let Some(mut param) = self.parse_self_param()? {
             param.attrs = attrs.into();
-            return self.recover_bad_self_param(param, is_trait_item);
+            return if is_self_allowed {
+                Ok(param)
+            } else {
+                self.recover_bad_self_param(param, is_trait_item)
+            };
         }
 
         let is_name_required = is_name_required(&self.token);
@@ -1208,6 +1215,7 @@ impl<'a> Parser<'a> {
                 };
             match p.parse_param_general(
                 false,
+                false,
                 allow_c_variadic,
                 do_not_enforce_named_arguments_for_c_variadic
             ) {
@@ -1361,60 +1369,25 @@ impl<'a> Parser<'a> {
         Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident)))
     }
 
-    /// Returns the parsed optional self parameter with attributes and whether a self
-    /// shortcut was used.
-    fn parse_self_parameter_with_attrs(&mut self) -> PResult<'a, Option<Param>> {
-        let attrs = self.parse_outer_attributes()?;
-        let param_opt = self.parse_self_param()?;
-        Ok(param_opt.map(|mut param| {
-            param.attrs = attrs.into();
-            param
-        }))
-    }
-
     /// Parses the parameter list and result type of a function that may have a `self` parameter.
-    fn parse_fn_decl_with_self<F>(&mut self, parse_param_fn: F) -> PResult<'a, P<FnDecl>>
-        where F: FnMut(&mut Parser<'a>) -> PResult<'a,  Param>,
-    {
-        self.expect(&token::OpenDelim(token::Paren))?;
-
-        // Parse optional self argument.
-        let self_param = self.parse_self_parameter_with_attrs()?;
-
-        // Parse the rest of the function parameter list.
-        let sep = SeqSep::trailing_allowed(token::Comma);
-        let (mut fn_inputs, recovered) = if let Some(self_param) = self_param {
-            if self.check(&token::CloseDelim(token::Paren)) {
-                (vec![self_param], false)
-            } else if self.eat(&token::Comma) {
-                let mut fn_inputs = vec![self_param];
-                let (mut input, _, recovered) = self.parse_seq_to_before_end(
-                    &token::CloseDelim(token::Paren), sep, parse_param_fn)?;
-                fn_inputs.append(&mut input);
-                (fn_inputs, recovered)
-            } else {
-                match self.expect_one_of(&[], &[]) {
-                    Err(err) => return Err(err),
-                    Ok(recovered) => (vec![self_param], recovered),
-                }
-            }
-        } else {
-            let (input, _, recovered) =
-                self.parse_seq_to_before_end(&token::CloseDelim(token::Paren),
-                                             sep,
-                                             parse_param_fn)?;
-            (input, recovered)
-        };
+    fn parse_fn_decl_with_self(
+        &mut self,
+        is_name_required: impl Copy + Fn(&token::Token) -> bool,
+    ) -> PResult<'a, P<FnDecl>> {
+        // Parse the arguments, starting out with `self` being allowed...
+        let mut is_self_allowed = true;
+        let (mut inputs, _): (Vec<_>, _) = self.parse_paren_comma_seq(|p| {
+            let res = p.parse_param_general(is_self_allowed, true, false, is_name_required);
+            // ...but now that we've parsed the first argument, `self` is no longer allowed.
+            is_self_allowed = false;
+            res
+        })?;
 
-        if !recovered {
-            // Parse closing paren and return type.
-            self.expect(&token::CloseDelim(token::Paren))?;
-        }
         // Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
-        self.deduplicate_recovered_params_names(&mut fn_inputs);
+        self.deduplicate_recovered_params_names(&mut inputs);
 
         Ok(P(FnDecl {
-            inputs: fn_inputs,
+            inputs,
             output: self.parse_ret_ty(true)?,
         }))
     }
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index 92b19b73e57..64c494416ff 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -424,13 +424,7 @@ impl<'a> Parser<'a> {
             } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) {
                 let ident = self.parse_ident().unwrap();
                 self.bump();  // `(`
-                let kw_name = if let Ok(Some(_)) = self.parse_self_parameter_with_attrs()
-                    .map_err(|mut e| e.cancel())
-                {
-                    "method"
-                } else {
-                    "function"
-                };
+                let kw_name = self.recover_first_param();
                 self.consume_block(token::Paren);
                 let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
                     self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]);
@@ -477,13 +471,7 @@ impl<'a> Parser<'a> {
                 self.eat_to_tokens(&[&token::Gt]);
                 self.bump();  // `>`
                 let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) {
-                    if let Ok(Some(_)) = self.parse_self_parameter_with_attrs()
-                        .map_err(|mut e| e.cancel())
-                    {
-                        ("fn", "method", false)
-                    } else {
-                        ("fn", "function", false)
-                    }
+                    ("fn", self.recover_first_param(), false)
                 } else if self.check(&token::OpenDelim(token::Brace)) {
                     ("struct", "struct", false)
                 } else {
@@ -505,6 +493,16 @@ impl<'a> Parser<'a> {
         self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility)
     }
 
+    fn recover_first_param(&mut self) -> &'static str {
+        match self.parse_outer_attributes()
+            .and_then(|_| self.parse_self_param())
+            .map_err(|mut e| e.cancel())
+        {
+            Ok(Some(_)) => "method",
+            _ => "function",
+        }
+    }
+
     /// This is the fall-through for parsing items.
     fn parse_macro_use_or_failure(
         &mut self,
@@ -861,9 +859,7 @@ impl<'a> Parser<'a> {
             let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
             let ident = self.parse_ident()?;
             let mut generics = self.parse_generics()?;
-            let decl = self.parse_fn_decl_with_self(|p| {
-                p.parse_param_general(true, false, |_| true)
-            })?;
+            let decl = self.parse_fn_decl_with_self(|_| true)?;
             generics.where_clause = self.parse_where_clause()?;
             *at_end = true;
             let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
@@ -1034,15 +1030,11 @@ impl<'a> Parser<'a> {
             let ident = self.parse_ident()?;
             let mut generics = self.parse_generics()?;
 
-            let decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| {
-                // This is somewhat dubious; We don't want to allow
-                // argument names to be left off if there is a
-                // definition...
-
-                // We don't allow argument names to be left off in edition 2018.
-                let is_name_required = p.token.span.rust_2018();
-                p.parse_param_general(true, false, |_| is_name_required)
-            })?;
+            // This is somewhat dubious; We don't want to allow
+            // argument names to be left off if there is a definition...
+            //
+            // We don't allow argument names to be left off in edition 2018.
+            let decl = self.parse_fn_decl_with_self(|t| t.span.rust_2018())?;
             generics.where_clause = self.parse_where_clause()?;
 
             let sig = ast::MethodSig {
diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.rs b/src/test/ui/const-generics/slice-const-param-mismatch.rs
new file mode 100644
index 00000000000..73c75ae6668
--- /dev/null
+++ b/src/test/ui/const-generics/slice-const-param-mismatch.rs
@@ -0,0 +1,14 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct ConstString<const T: &'static str>;
+struct ConstBytes<const T: &'static [u8]>;
+
+pub fn main() {
+    let _: ConstString<"Hello"> = ConstString::<"Hello">;
+    let _: ConstString<"Hello"> = ConstString::<"World">; //~ ERROR mismatched types
+    let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">;
+    let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //~ ERROR mismatched types
+    let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
+    let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.stderr
new file mode 100644
index 00000000000..72369ab24eb
--- /dev/null
+++ b/src/test/ui/const-generics/slice-const-param-mismatch.stderr
@@ -0,0 +1,38 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/slice-const-param-mismatch.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:9:35
+   |
+LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
+   |
+   = note: expected type `ConstString<>`
+              found type `ConstString<>`
+
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:11:33
+   |
+LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
+   |                                  ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
+   |
+   = note: expected type `ConstString<>`
+              found type `ConstString<>`
+
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:13:33
+   |
+LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
+   |                                 ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
+   |
+   = note: expected type `ConstBytes<>`
+              found type `ConstBytes<>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/slice-const-param.rs b/src/test/ui/const-generics/slice-const-param.rs
new file mode 100644
index 00000000000..2629caa3921
--- /dev/null
+++ b/src/test/ui/const-generics/slice-const-param.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+pub fn function_with_str<const STRING: &'static str>() -> &'static str {
+    STRING
+}
+
+pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
+    BYTES
+}
+
+pub fn main() {
+    assert_eq!(function_with_str::<"Rust">(), "Rust");
+    assert_eq!(function_with_str::<"ℇ㇈↦">(), "ℇ㇈↦");
+    assert_eq!(function_with_bytes::<b"AAAA">(), &[0x41, 0x41, 0x41, 0x41]);
+    assert_eq!(function_with_bytes::<{&[0x41, 0x41, 0x41, 0x41]}>(), b"AAAA");
+}
diff --git a/src/test/ui/const-generics/slice-const-param.stderr b/src/test/ui/const-generics/slice-const-param.stderr
new file mode 100644
index 00000000000..79214a34fdb
--- /dev/null
+++ b/src/test/ui/const-generics/slice-const-param.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/slice-const-param.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index b9681db87b6..97121575527 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -1,6 +1,9 @@
 error[E0423]: expected value, found struct `Empty1`
   --> $DIR/empty-struct-braces-expr.rs:15:14
    |
+LL | struct Empty1 {}
+   | ---------------- `Empty1` defined here
+...
 LL |     let e1 = Empty1;
    |              ^^^^^^
    |              |
@@ -10,6 +13,9 @@ LL |     let e1 = Empty1;
 error[E0423]: expected function, found struct `Empty1`
   --> $DIR/empty-struct-braces-expr.rs:16:14
    |
+LL | struct Empty1 {}
+   | ---------------- `Empty1` defined here
+...
 LL |     let e1 = Empty1();
    |              ^^^^^^
    |              |
@@ -19,12 +25,18 @@ LL |     let e1 = Empty1();
 error[E0423]: expected value, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-expr.rs:17:14
    |
+LL |     Empty3 {}
+   |     --------- `E::Empty3` defined here
+...
 LL |     let e3 = E::Empty3;
    |              ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
 
 error[E0423]: expected function, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-expr.rs:18:14
    |
+LL |     Empty3 {}
+   |     --------- `E::Empty3` defined here
+...
 LL |     let e3 = E::Empty3();
    |              ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
 
diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
index 6c361c70344..271e811a2fd 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
@@ -1,6 +1,9 @@
 error[E0532]: expected unit struct/variant or constant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-1.rs:24:9
    |
+LL |     Empty3 {}
+   |     --------- `E::Empty3` defined here
+...
 LL |         E::Empty3 => ()
    |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
 
diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
index 12047b5880c..33524737888 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
@@ -1,6 +1,9 @@
 error[E0532]: expected tuple struct/variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-pat-2.rs:15:9
    |
+LL | struct Empty1 {}
+   | ---------------- `Empty1` defined here
+...
 LL |         Empty1() => ()
    |         ^^^^^^
    |         |
@@ -19,6 +22,9 @@ LL |         XEmpty1() => ()
 error[E0532]: expected tuple struct/variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-pat-2.rs:21:9
    |
+LL | struct Empty1 {}
+   | ---------------- `Empty1` defined here
+...
 LL |         Empty1(..) => ()
    |         ^^^^^^
    |         |
diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
index af8731b5f05..aefdd772b1b 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
@@ -1,6 +1,9 @@
 error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-3.rs:17:9
    |
+LL |     Empty3 {}
+   |     --------- `E::Empty3` defined here
+...
 LL |         E::Empty3() => ()
    |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
 
@@ -16,6 +19,9 @@ LL |         XE::XEmpty3() => ()
 error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-3.rs:25:9
    |
+LL |     Empty3 {}
+   |     --------- `E::Empty3` defined here
+...
 LL |         E::Empty3(..) => ()
    |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
 
diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr
index 6c15e7bf282..4b828c0d942 100644
--- a/src/test/ui/empty/empty-struct-tuple-pat.stderr
+++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr
@@ -19,8 +19,11 @@ LL |         XEmpty6 => ()
 error[E0532]: expected unit struct/variant or constant, found tuple variant `E::Empty4`
   --> $DIR/empty-struct-tuple-pat.rs:29:9
    |
+LL |     Empty4()
+   |     -------- `E::Empty4` defined here
+...
 LL |         E::Empty4 => ()
-   |         ^^^^^^^^^ did you mean `E::Empty4 ( /* fields */ )`?
+   |         ^^^^^^^^^ did you mean `E::Empty4( /* fields */ )`?
 
 error[E0532]: expected unit struct/variant or constant, found tuple variant `XE::XEmpty5`
   --> $DIR/empty-struct-tuple-pat.rs:33:9
@@ -29,7 +32,7 @@ LL |         XE::XEmpty5 => (),
    |         ^^^^-------
    |         |   |
    |         |   help: a unit variant with a similar name exists: `XEmpty4`
-   |         did you mean `XE::XEmpty5 ( /* fields */ )`?
+   |         did you mean `XE::XEmpty5( /* fields */ )`?
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index ec240003f91..ce631ca4bf7 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -27,6 +27,9 @@ LL |     for _ in (std::ops::Range { start: 0, end: 10 }) {}
 error[E0423]: expected function, found struct `Foo`
   --> $DIR/E0423.rs:4:13
    |
+LL |     struct Foo { a: bool };
+   |     ---------------------- `Foo` defined here
+LL | 
 LL |     let f = Foo();
    |             ^^^
    |             |
diff --git a/src/test/ui/issues/issue-19086.stderr b/src/test/ui/issues/issue-19086.stderr
index d2b9b90890e..e2229cbc209 100644
--- a/src/test/ui/issues/issue-19086.stderr
+++ b/src/test/ui/issues/issue-19086.stderr
@@ -1,6 +1,9 @@
 error[E0532]: expected tuple struct/variant, found struct variant `FooB`
   --> $DIR/issue-19086.rs:10:9
    |
+LL |     FooB { x: i32, y: i32 }
+   |     ----------------------- `FooB` defined here
+...
 LL |         FooB(a, b) => println!("{} {}", a, b),
    |         ^^^^ did you mean `FooB { /* fields */ }`?
 
diff --git a/src/test/ui/issues/issue-32004.stderr b/src/test/ui/issues/issue-32004.stderr
index b56fa949acb..e9a5e217392 100644
--- a/src/test/ui/issues/issue-32004.stderr
+++ b/src/test/ui/issues/issue-32004.stderr
@@ -1,11 +1,14 @@
 error[E0532]: expected unit struct/variant or constant, found tuple variant `Foo::Bar`
   --> $DIR/issue-32004.rs:10:9
    |
+LL |     Bar(i32),
+   |     -------- `Foo::Bar` defined here
+...
 LL |         Foo::Bar => {}
    |         ^^^^^---
    |         |    |
    |         |    help: a unit variant with a similar name exists: `Baz`
-   |         did you mean `Foo::Bar ( /* fields */ )`?
+   |         did you mean `Foo::Bar( /* fields */ )`?
 
 error[E0532]: expected tuple struct/variant, found unit struct `S`
   --> $DIR/issue-32004.rs:16:9
diff --git a/src/test/ui/issues/issue-63983.stderr b/src/test/ui/issues/issue-63983.stderr
index 67acd1d57c2..8949c475b6f 100644
--- a/src/test/ui/issues/issue-63983.stderr
+++ b/src/test/ui/issues/issue-63983.stderr
@@ -1,12 +1,18 @@
 error[E0532]: expected unit struct/variant or constant, found tuple variant `MyEnum::Tuple`
   --> $DIR/issue-63983.rs:8:9
    |
+LL |     Tuple(i32),
+   |     ---------- `MyEnum::Tuple` defined here
+...
 LL |         MyEnum::Tuple => "",
-   |         ^^^^^^^^^^^^^ did you mean `MyEnum::Tuple ( /* fields */ )`?
+   |         ^^^^^^^^^^^^^ did you mean `MyEnum::Tuple( /* fields */ )`?
 
 error[E0532]: expected unit struct/variant or constant, found struct variant `MyEnum::Struct`
   --> $DIR/issue-63983.rs:10:9
    |
+LL |     Struct{ s: i32 },
+   |     ---------------- `MyEnum::Struct` defined here
+...
 LL |         MyEnum::Struct => "",
    |         ^^^^^^^^^^^^^^ did you mean `MyEnum::Struct { /* fields */ }`?
 
diff --git a/src/test/ui/lint/lint-unused-variables.rs b/src/test/ui/lint/lint-unused-variables.rs
index 1a6b5183f0f..6850e999242 100644
--- a/src/test/ui/lint/lint-unused-variables.rs
+++ b/src/test/ui/lint/lint-unused-variables.rs
@@ -29,6 +29,11 @@ impl RefStruct {
         b: i32,
         //~^ ERROR unused variable: `b`
     ) {}
+    fn issue_64682_associated_fn(
+        #[allow(unused_variables)] a: i32,
+        b: i32,
+        //~^ ERROR unused variable: `b`
+    ) {}
 }
 trait RefTrait {
     fn bar(
@@ -37,6 +42,11 @@ trait RefTrait {
         b: i32,
         //~^ ERROR unused variable: `b`
     ) {}
+    fn issue_64682_associated_fn(
+        #[allow(unused_variables)] a: i32,
+        b: i32,
+        //~^ ERROR unused variable: `b`
+    ) {}
 }
 impl RefTrait for RefStruct {
     fn bar(
@@ -45,6 +55,11 @@ impl RefTrait for RefStruct {
         b: i32,
         //~^ ERROR unused variable: `b`
     ) {}
+    fn issue_64682_associated_fn(
+        #[allow(unused_variables)] a: i32,
+        b: i32,
+        //~^ ERROR unused variable: `b`
+    ) {}
 }
 
 fn main() {
diff --git a/src/test/ui/lint/lint-unused-variables.stderr b/src/test/ui/lint/lint-unused-variables.stderr
index 7ed5669e33c..f8419bf5066 100644
--- a/src/test/ui/lint/lint-unused-variables.stderr
+++ b/src/test/ui/lint/lint-unused-variables.stderr
@@ -17,19 +17,25 @@ LL |     b: i32,
    |     ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `a`
-  --> $DIR/lint-unused-variables.rs:53:9
+  --> $DIR/lint-unused-variables.rs:68:9
    |
 LL |         a: i32,
    |         ^ help: consider prefixing with an underscore: `_a`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:59:9
+  --> $DIR/lint-unused-variables.rs:74:9
    |
 LL |         b: i32,
    |         ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:37:9
+  --> $DIR/lint-unused-variables.rs:42:9
+   |
+LL |         b: i32,
+   |         ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:47:9
    |
 LL |         b: i32,
    |         ^ help: consider prefixing with an underscore: `_b`
@@ -47,10 +53,22 @@ LL |         b: i32,
    |         ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `b`
-  --> $DIR/lint-unused-variables.rs:45:9
+  --> $DIR/lint-unused-variables.rs:34:9
+   |
+LL |         b: i32,
+   |         ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:55:9
+   |
+LL |         b: i32,
+   |         ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:60:9
    |
 LL |         b: i32,
    |         ^ help: consider prefixing with an underscore: `_b`
 
-error: aborting due to 8 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/methods/method-path-in-pattern.rs b/src/test/ui/methods/method-path-in-pattern.rs
index fb1cf7f71e7..21a91f3f32b 100644
--- a/src/test/ui/methods/method-path-in-pattern.rs
+++ b/src/test/ui/methods/method-path-in-pattern.rs
@@ -23,4 +23,10 @@ fn main() {
         <Foo>::trait_bar => {}
         //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::trait_bar`
     }
+    if let Foo::bar = 0u32 {}
+    //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::bar`
+    if let <Foo>::bar = 0u32 {}
+    //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::bar`
+    if let Foo::trait_bar = 0u32 {}
+    //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::trait_bar`
 }
diff --git a/src/test/ui/methods/method-path-in-pattern.stderr b/src/test/ui/methods/method-path-in-pattern.stderr
index 3f53ad76882..257fff4c37d 100644
--- a/src/test/ui/methods/method-path-in-pattern.stderr
+++ b/src/test/ui/methods/method-path-in-pattern.stderr
@@ -16,5 +16,24 @@ error[E0533]: expected unit struct/variant or constant, found method `<Foo>::tra
 LL |         <Foo>::trait_bar => {}
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error[E0533]: expected unit struct/variant or constant, found method `<Foo>::bar`
+  --> $DIR/method-path-in-pattern.rs:26:12
+   |
+LL |     if let Foo::bar = 0u32 {}
+   |            ^^^^^^^^
+
+error[E0533]: expected unit struct/variant or constant, found method `<Foo>::bar`
+  --> $DIR/method-path-in-pattern.rs:28:12
+   |
+LL |     if let <Foo>::bar = 0u32 {}
+   |            ^^^^^^^^^^
+
+error[E0533]: expected unit struct/variant or constant, found method `<Foo>::trait_bar`
+  --> $DIR/method-path-in-pattern.rs:30:12
+   |
+LL |     if let Foo::trait_bar = 0u32 {}
+   |            ^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 
+For more information about this error, try `rustc --explain E0533`.
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index aa21928aaef..77da07f40d5 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -37,6 +37,9 @@ LL | use namespace_mix::xm2::S;
 error[E0423]: expected value, found struct variant `m7::V`
   --> $DIR/namespace-mix.rs:100:11
    |
+LL |         V {},
+   |         ---- `m7::V` defined here
+...
 LL |     check(m7::V);
    |           ^^^^^ did you mean `m7::V { /* fields */ }`?
 help: a tuple variant with a similar name exists
diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr
index b46d3ca9c23..32bb88d31c4 100644
--- a/src/test/ui/parser/recover-from-bad-variant.stderr
+++ b/src/test/ui/parser/recover-from-bad-variant.stderr
@@ -12,6 +12,9 @@ LL |     let x = Enum::Foo(a: 3, b: 4);
 error[E0532]: expected tuple struct/variant, found struct variant `Enum::Foo`
   --> $DIR/recover-from-bad-variant.rs:10:9
    |
+LL |     Foo { a: usize, b: usize },
+   |     -------------------------- `Enum::Foo` defined here
+...
 LL |         Enum::Foo(a, b) => {}
    |         ^^^^^^^^^ did you mean `Enum::Foo { /* fields */ }`?
 
diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr
index b8d3b744e83..3e8fcdc7ca3 100644
--- a/src/test/ui/qualified/qualified-path-params.stderr
+++ b/src/test/ui/qualified/qualified-path-params.stderr
@@ -15,4 +15,5 @@ LL |         0 ..= <S as Tr>::A::f::<u8> => {}
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0029`.
+Some errors have detailed explanations: E0029, E0533.
+For more information about an error, try `rustc --explain E0029`.
diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr
index 293f290f82f..c76e5ef8b36 100644
--- a/src/test/ui/resolve/issue-18252.stderr
+++ b/src/test/ui/resolve/issue-18252.stderr
@@ -1,6 +1,9 @@
 error[E0423]: expected function, found struct variant `Foo::Variant`
   --> $DIR/issue-18252.rs:6:13
    |
+LL |     Variant { x: usize }
+   |     -------------------- `Foo::Variant` defined here
+...
 LL |     let f = Foo::Variant(42);
    |             ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`?
 
diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr
index 56a0e397b85..4d20f158026 100644
--- a/src/test/ui/resolve/issue-19452.stderr
+++ b/src/test/ui/resolve/issue-19452.stderr
@@ -1,6 +1,9 @@
 error[E0423]: expected value, found struct variant `Homura::Madoka`
   --> $DIR/issue-19452.rs:10:18
    |
+LL |     Madoka { age: u32 }
+   |     ------------------- `Homura::Madoka` defined here
+...
 LL |     let homura = Homura::Madoka;
    |                  ^^^^^^^^^^^^^^ did you mean `Homura::Madoka { /* fields */ }`?
 
diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr
index c97fb4db6be..d9a28e63dce 100644
--- a/src/test/ui/resolve/issue-39226.stderr
+++ b/src/test/ui/resolve/issue-39226.stderr
@@ -1,6 +1,9 @@
 error[E0423]: expected value, found struct `Handle`
   --> $DIR/issue-39226.rs:11:17
    |
+LL | struct Handle {}
+   | ---------------- `Handle` defined here
+...
 LL |         handle: Handle
    |                 ^^^^^^
    |                 |
diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr
index 9a46f0d7742..3fdc7acb274 100644
--- a/src/test/ui/resolve/issue-6702.stderr
+++ b/src/test/ui/resolve/issue-6702.stderr
@@ -1,8 +1,13 @@
 error[E0423]: expected function, found struct `Monster`
   --> $DIR/issue-6702.rs:7:14
    |
-LL |     let _m = Monster();
-   |              ^^^^^^^ did you mean `Monster { /* fields */ }`?
+LL | / struct Monster {
+LL | |     damage: isize
+LL | | }
+   | |_- `Monster` defined here
+...
+LL |       let _m = Monster();
+   |                ^^^^^^^ did you mean `Monster { /* fields */ }`?
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index 2538bbbf806..7d8d1d0abfc 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -33,8 +33,13 @@ LL |         m::Z::Unit;
 error[E0423]: expected value, found struct variant `Z::Struct`
   --> $DIR/privacy-enum-ctor.rs:29:20
    |
-LL |         let _: Z = Z::Struct;
-   |                    ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`?
+LL | /             Struct {
+LL | |                 s: u8,
+LL | |             },
+   | |_____________- `Z::Struct` defined here
+...
+LL |           let _: Z = Z::Struct;
+   |                      ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`?
 
 error[E0423]: expected value, found enum `m::E`
   --> $DIR/privacy-enum-ctor.rs:41:16
@@ -63,8 +68,13 @@ LL | use std::f64::consts::E;
 error[E0423]: expected value, found struct variant `m::E::Struct`
   --> $DIR/privacy-enum-ctor.rs:45:16
    |
-LL |     let _: E = m::E::Struct;
-   |                ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`?
+LL | /         Struct {
+LL | |             s: u8,
+LL | |         },
+   | |_________- `m::E::Struct` defined here
+...
+LL |       let _: E = m::E::Struct;
+   |                  ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`?
 
 error[E0423]: expected value, found enum `E`
   --> $DIR/privacy-enum-ctor.rs:49:16
@@ -89,8 +99,13 @@ LL | use std::f64::consts::E;
 error[E0423]: expected value, found struct variant `E::Struct`
   --> $DIR/privacy-enum-ctor.rs:53:16
    |
-LL |     let _: E = E::Struct;
-   |                ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`?
+LL | /         Struct {
+LL | |             s: u8,
+LL | |         },
+   | |_________- `E::Struct` defined here
+...
+LL |       let _: E = E::Struct;
+   |                  ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`?
 
 error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:57:12
@@ -151,8 +166,13 @@ LL | use m::n::Z;
 error[E0423]: expected value, found struct variant `m::n::Z::Struct`
   --> $DIR/privacy-enum-ctor.rs:64:16
    |
-LL |     let _: Z = m::n::Z::Struct;
-   |                ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`?
+LL | /             Struct {
+LL | |                 s: u8,
+LL | |             },
+   | |_____________- `m::n::Z::Struct` defined here
+...
+LL |       let _: Z = m::n::Z::Struct;
+   |                  ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`?
 
 error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:68:12
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index 72d62fe45ce..979367bc623 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -16,8 +16,13 @@ LL |     S;
 error[E0423]: expected value, found struct `S2`
   --> $DIR/privacy-struct-ctor.rs:38:5
    |
-LL |     S2;
-   |     ^^ did you mean `S2 { /* fields */ }`?
+LL | /     pub struct S2 {
+LL | |         s: u8
+LL | |     }
+   | |_____- `S2` defined here
+...
+LL |       S2;
+   |       ^^ did you mean `S2 { /* fields */ }`?
 
 error[E0423]: expected value, found struct `xcrate::S`
   --> $DIR/privacy-struct-ctor.rs:43:5
diff --git a/src/test/ui/rfc-2565-param-attrs/attr-without-param.rs b/src/test/ui/rfc-2565-param-attrs/attr-without-param.rs
new file mode 100644
index 00000000000..eeb2191bab4
--- /dev/null
+++ b/src/test/ui/rfc-2565-param-attrs/attr-without-param.rs
@@ -0,0 +1,16 @@
+#[cfg(FALSE)]
+impl S {
+    fn f(#[attr]) {} //~ ERROR expected parameter name, found `)`
+}
+
+#[cfg(FALSE)]
+impl T for S {
+    fn f(#[attr]) {} //~ ERROR expected parameter name, found `)`
+}
+
+#[cfg(FALSE)]
+trait T {
+    fn f(#[attr]); //~ ERROR expected argument name, found `)`
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr b/src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr
new file mode 100644
index 00000000000..26dff4d4b30
--- /dev/null
+++ b/src/test/ui/rfc-2565-param-attrs/attr-without-param.stderr
@@ -0,0 +1,20 @@
+error: expected parameter name, found `)`
+  --> $DIR/attr-without-param.rs:3:17
+   |
+LL |     fn f(#[attr]) {}
+   |                 ^ expected parameter name
+
+error: expected parameter name, found `)`
+  --> $DIR/attr-without-param.rs:8:17
+   |
+LL |     fn f(#[attr]) {}
+   |                 ^ expected parameter name
+
+error: expected argument name, found `)`
+  --> $DIR/attr-without-param.rs:13:17
+   |
+LL |     fn f(#[attr]);
+   |                 ^ expected argument name
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs
index 71815e3c089..c537c1034b5 100644
--- a/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs
+++ b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs
@@ -11,7 +11,6 @@ macro_rules! checker {
     ($attr_name:ident, $expected:literal) => {
         #[proc_macro_attribute]
         pub fn $attr_name(attr: TokenStream, input: TokenStream) -> TokenStream {
-            assert!(attr.to_string().is_empty());
             assert_eq!(input.to_string(), $expected);
             TokenStream::new()
         }
@@ -28,7 +27,18 @@ checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1: u8) { }");
 checker!(attr_inherent_2, "fn inherent2(#[a1] &self, #[a2] arg1: u8) { }");
 checker!(attr_inherent_3, "fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) { }");
 checker!(attr_inherent_4, "fn inherent4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8) { }");
+checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) { }");
 checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1: u8);");
 checker!(attr_trait_2, "fn trait2(#[a1] &self, #[a2] arg1: u8);");
 checker!(attr_trait_3, "fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);");
 checker!(attr_trait_4, "fn trait4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8, #[a3] Vec<u8>);");
+checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);");
+checker!(rename_params, r#"impl Foo {
+    fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) { }
+    fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32,
+              #[angery(true)] c: u32) {
+    }
+    fn hello_self(#[a1] #[a2] &self, #[a1] #[a2] a: i32,
+                  #[what = "how"] b: i32, #[angery(true)] c: u32) {
+    }
+}"#);
diff --git a/src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs b/src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs
new file mode 100644
index 00000000000..670303906d2
--- /dev/null
+++ b/src/test/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs
@@ -0,0 +1,21 @@
+// aux-build:param-attrs.rs
+
+// check-pass
+
+extern crate param_attrs;
+
+use param_attrs::rename_params;
+
+#[rename_params(send_help)]
+impl Foo {
+    fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) {}
+    fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32, #[angery(true)] c: u32) {}
+    fn hello_self(
+        #[a1] #[a2] &self,
+        #[a1] #[a2] a: i32,
+        #[what = "how"] b: i32,
+        #[angery(true)] c: u32
+    ) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
index c4684a3fa82..bf09171c9a1 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
@@ -64,6 +64,21 @@ impl SelfStruct {
         #[no_mangle] b: i32,
         //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
     ) {}
+
+    fn issue_64682_associated_fn(
+        /// Foo
+        //~^ ERROR documentation comments cannot be applied to function
+        #[test] a: i32,
+        //~^ ERROR expected an inert attribute, found an attribute macro
+        /// Baz
+        //~^ ERROR documentation comments cannot be applied to function
+        #[must_use]
+        //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
+        /// Qux
+        //~^ ERROR documentation comments cannot be applied to function
+        #[no_mangle] b: i32,
+        //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
+    ) {}
 }
 
 struct RefStruct {}
@@ -104,7 +119,23 @@ trait RefTrait {
         #[no_mangle] b: i32,
         //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
     ) {}
+
+    fn issue_64682_associated_fn(
+        /// Foo
+        //~^ ERROR documentation comments cannot be applied to function
+        #[test] a: i32,
+        //~^ ERROR expected an inert attribute, found an attribute macro
+        /// Baz
+        //~^ ERROR documentation comments cannot be applied to function
+        #[must_use]
+        //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
+        /// Qux
+        //~^ ERROR documentation comments cannot be applied to function
+        #[no_mangle] b: i32,
+        //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in
+    ) {}
 }
+
 impl RefTrait for RefStruct {
     fn foo(
         /// Foo
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
index 0fc6ca2f7f3..4d0349e8765 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
@@ -23,25 +23,37 @@ LL |         #[test] a: i32,
    |         ^^^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:77:9
+  --> $DIR/param-attrs-builtin-attrs.rs:71:9
    |
 LL |         #[test] a: i32,
    |         ^^^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:96:9
+  --> $DIR/param-attrs-builtin-attrs.rs:92:9
    |
 LL |         #[test] a: i32,
    |         ^^^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:115:9
+  --> $DIR/param-attrs-builtin-attrs.rs:111:9
    |
 LL |         #[test] a: i32,
    |         ^^^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/param-attrs-builtin-attrs.rs:132:9
+  --> $DIR/param-attrs-builtin-attrs.rs:126:9
+   |
+LL |         #[test] a: i32,
+   |         ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:146:9
+   |
+LL |         #[test] a: i32,
+   |         ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:163:9
    |
 LL |         #[test] a: u32,
    |         ^^^^^^^
@@ -173,142 +185,202 @@ LL |         #[no_mangle] b: i32,
    |         ^^^^^^^^^^^^
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:72:9
+  --> $DIR/param-attrs-builtin-attrs.rs:69:9
    |
 LL |         /// Foo
    |         ^^^^^^^ doc comments are not allowed here
 
 error: documentation comments cannot be applied to function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:73:9
+   |
+LL |         /// Baz
+   |         ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
   --> $DIR/param-attrs-builtin-attrs.rs:75:9
    |
+LL |         #[must_use]
+   |         ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:77:9
+   |
+LL |         /// Qux
+   |         ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:79:9
+   |
+LL |         #[no_mangle] b: i32,
+   |         ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:87:9
+   |
+LL |         /// Foo
+   |         ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:90:9
+   |
 LL |         /// Bar
    |         ^^^^^^^ doc comments are not allowed here
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:79:9
+  --> $DIR/param-attrs-builtin-attrs.rs:94:9
    |
 LL |         /// Baz
    |         ^^^^^^^ doc comments are not allowed here
 
 error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:81:9
+  --> $DIR/param-attrs-builtin-attrs.rs:96:9
    |
 LL |         #[must_use]
    |         ^^^^^^^^^^^
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:83:9
+  --> $DIR/param-attrs-builtin-attrs.rs:98:9
    |
 LL |         /// Qux
    |         ^^^^^^^ doc comments are not allowed here
 
 error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:85:9
+  --> $DIR/param-attrs-builtin-attrs.rs:100:9
    |
 LL |         #[no_mangle] b: i32,
    |         ^^^^^^^^^^^^
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:91:9
+  --> $DIR/param-attrs-builtin-attrs.rs:106:9
    |
 LL |         /// Foo
    |         ^^^^^^^ doc comments are not allowed here
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:94:9
+  --> $DIR/param-attrs-builtin-attrs.rs:109:9
    |
 LL |         /// Bar
    |         ^^^^^^^ doc comments are not allowed here
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:98:9
+  --> $DIR/param-attrs-builtin-attrs.rs:113:9
    |
 LL |         /// Baz
    |         ^^^^^^^ doc comments are not allowed here
 
 error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:100:9
+  --> $DIR/param-attrs-builtin-attrs.rs:115:9
    |
 LL |         #[must_use]
    |         ^^^^^^^^^^^
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:102:9
+  --> $DIR/param-attrs-builtin-attrs.rs:117:9
    |
 LL |         /// Qux
    |         ^^^^^^^ doc comments are not allowed here
 
 error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:104:9
+  --> $DIR/param-attrs-builtin-attrs.rs:119:9
    |
 LL |         #[no_mangle] b: i32,
    |         ^^^^^^^^^^^^
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:110:9
+  --> $DIR/param-attrs-builtin-attrs.rs:124:9
    |
 LL |         /// Foo
    |         ^^^^^^^ doc comments are not allowed here
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:113:9
+  --> $DIR/param-attrs-builtin-attrs.rs:128:9
+   |
+LL |         /// Baz
+   |         ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:130:9
+   |
+LL |         #[must_use]
+   |         ^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:132:9
+   |
+LL |         /// Qux
+   |         ^^^^^^^ doc comments are not allowed here
+
+error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:134:9
+   |
+LL |         #[no_mangle] b: i32,
+   |         ^^^^^^^^^^^^
+
+error: documentation comments cannot be applied to function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:141:9
+   |
+LL |         /// Foo
+   |         ^^^^^^^ doc comments are not allowed here
+
+error: documentation comments cannot be applied to function parameters
+  --> $DIR/param-attrs-builtin-attrs.rs:144:9
    |
 LL |         /// Bar
    |         ^^^^^^^ doc comments are not allowed here
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:117:9
+  --> $DIR/param-attrs-builtin-attrs.rs:148:9
    |
 LL |         /// Baz
    |         ^^^^^^^ doc comments are not allowed here
 
 error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:119:9
+  --> $DIR/param-attrs-builtin-attrs.rs:150:9
    |
 LL |         #[must_use]
    |         ^^^^^^^^^^^
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:121:9
+  --> $DIR/param-attrs-builtin-attrs.rs:152:9
    |
 LL |         /// Qux
    |         ^^^^^^^ doc comments are not allowed here
 
 error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:123:9
+  --> $DIR/param-attrs-builtin-attrs.rs:154:9
    |
 LL |         #[no_mangle] b: i32,
    |         ^^^^^^^^^^^^
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:130:9
+  --> $DIR/param-attrs-builtin-attrs.rs:161:9
    |
 LL |         /// Foo
    |         ^^^^^^^ doc comments are not allowed here
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:134:9
+  --> $DIR/param-attrs-builtin-attrs.rs:165:9
    |
 LL |         /// Bar
    |         ^^^^^^^ doc comments are not allowed here
 
 error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:136:9
+  --> $DIR/param-attrs-builtin-attrs.rs:167:9
    |
 LL |         #[must_use]
    |         ^^^^^^^^^^^
 
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:138:9
+  --> $DIR/param-attrs-builtin-attrs.rs:169:9
    |
 LL |         /// Baz
    |         ^^^^^^^ doc comments are not allowed here
 
 error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters
-  --> $DIR/param-attrs-builtin-attrs.rs:140:9
+  --> $DIR/param-attrs-builtin-attrs.rs:171:9
    |
 LL |         #[no_mangle] b: i32
    |         ^^^^^^^^^^^^
 
-error: aborting due to 52 previous errors
+error: aborting due to 64 previous errors
 
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs
index d44ff14e992..a4d9d32b514 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs
@@ -51,6 +51,14 @@ impl RefStruct {
         //~^ ERROR unused variable: `c`
         #[cfg_attr(something, cfg(nothing))] d: i32,
     ) {}
+    fn issue_64682_associated_fn(
+        #[cfg(nothing)] a: i32,
+        #[cfg(something)] b: i32,
+        //~^ ERROR unused variable: `b`
+        #[cfg_attr(nothing, cfg(nothing))] c: i32,
+        //~^ ERROR unused variable: `c`
+        #[cfg_attr(something, cfg(nothing))] d: i32,
+    ) {}
 }
 trait RefTrait {
     fn bar(
@@ -62,6 +70,14 @@ trait RefTrait {
         //~^ ERROR unused variable: `c`
         #[cfg_attr(something, cfg(nothing))] d: i32,
     ) {}
+    fn issue_64682_associated_fn(
+        #[cfg(nothing)] a: i32,
+        #[cfg(something)] b: i32,
+        //~^ ERROR unused variable: `b`
+        #[cfg_attr(nothing, cfg(nothing))] c: i32,
+        //~^ ERROR unused variable: `c`
+        #[cfg_attr(something, cfg(nothing))] d: i32,
+    ) {}
 }
 impl RefTrait for RefStruct {
     fn bar(
@@ -73,6 +89,14 @@ impl RefTrait for RefStruct {
         //~^ ERROR unused variable: `c`
         #[cfg_attr(something, cfg(nothing))] d: i32,
     ) {}
+    fn issue_64682_associated_fn(
+        #[cfg(nothing)] a: i32,
+        #[cfg(something)] b: i32,
+        //~^ ERROR unused variable: `b`
+        #[cfg_attr(nothing, cfg(nothing))] c: i32,
+        //~^ ERROR unused variable: `c`
+        #[cfg_attr(something, cfg(nothing))] d: i32,
+    ) {}
 }
 
 fn main() {
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr
index 3232e2a0411..8d9571d09a8 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr
@@ -23,31 +23,43 @@ LL |     #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                        ^ help: consider prefixing with an underscore: `_c`
 
 error: unused variable: `a`
-  --> $DIR/param-attrs-cfg.rs:83:27
+  --> $DIR/param-attrs-cfg.rs:107:27
    |
 LL |         #[cfg(something)] a: i32,
    |                           ^ help: consider prefixing with an underscore: `_a`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:89:27
+  --> $DIR/param-attrs-cfg.rs:113:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:91:44
+  --> $DIR/param-attrs-cfg.rs:115:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: consider prefixing with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:59:27
+  --> $DIR/param-attrs-cfg.rs:67:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:61:44
+  --> $DIR/param-attrs-cfg.rs:69:44
+   |
+LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
+   |                                            ^ help: consider prefixing with an underscore: `_c`
+
+error: unused variable: `b`
+  --> $DIR/param-attrs-cfg.rs:75:27
+   |
+LL |         #[cfg(something)] b: i32,
+   |                           ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `c`
+  --> $DIR/param-attrs-cfg.rs:77:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: consider prefixing with an underscore: `_c`
@@ -71,16 +83,40 @@ LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: consider prefixing with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:70:27
+  --> $DIR/param-attrs-cfg.rs:56:27
+   |
+LL |         #[cfg(something)] b: i32,
+   |                           ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `c`
+  --> $DIR/param-attrs-cfg.rs:58:44
+   |
+LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
+   |                                            ^ help: consider prefixing with an underscore: `_c`
+
+error: unused variable: `b`
+  --> $DIR/param-attrs-cfg.rs:86:27
+   |
+LL |         #[cfg(something)] b: i32,
+   |                           ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `c`
+  --> $DIR/param-attrs-cfg.rs:88:44
+   |
+LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
+   |                                            ^ help: consider prefixing with an underscore: `_c`
+
+error: unused variable: `b`
+  --> $DIR/param-attrs-cfg.rs:94:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:72:44
+  --> $DIR/param-attrs-cfg.rs:96:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: consider prefixing with an underscore: `_c`
 
-error: aborting due to 13 previous errors
+error: aborting due to 19 previous errors
 
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs
index fb86020d992..1183ac65b9a 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs
@@ -36,6 +36,9 @@ impl W {
 
     #[attr_inherent_4]
     fn inherent4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8) {}
+
+    #[attr_inherent_issue_64682]
+    fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) {}
 }
 
 trait A {
@@ -50,6 +53,9 @@ trait A {
 
     #[attr_trait_4]
     fn trait4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8, #[a3] Vec<u8>);
+
+    #[attr_trait_issue_64682]
+    fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs
index e2680446f85..be9085d5878 100644
--- a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs
+++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs
@@ -38,6 +38,9 @@ impl W {
     fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
     //~^ ERROR expected an inert attribute, found an attribute macro
     //~| ERROR expected an inert attribute, found an attribute macro
+    fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
 }
 
 trait A {
@@ -54,6 +57,9 @@ trait A {
     //~^ ERROR expected an inert attribute, found an attribute macro
     //~| ERROR expected an inert attribute, found an attribute macro
     //~| ERROR expected an inert attribute, found an attribute macro
+    fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr
index 4654dc1b496..1cc3c3d8228 100644
--- a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr
+++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr
@@ -95,58 +95,82 @@ LL |     fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
    |                                             ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:44:15
+  --> $DIR/proc-macro-cannot-be-used.rs:41:38
+   |
+LL |     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
+   |                                      ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:41:54
+   |
+LL |     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {}
+   |                                                      ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:47:15
    |
 LL |     fn trait1(#[id] self, #[id] arg1: u8);
    |               ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:44:27
+  --> $DIR/proc-macro-cannot-be-used.rs:47:27
    |
 LL |     fn trait1(#[id] self, #[id] arg1: u8);
    |                           ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:47:15
+  --> $DIR/proc-macro-cannot-be-used.rs:50:15
    |
 LL |     fn trait2(#[id] &self, #[id] arg1: u8);
    |               ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:47:28
+  --> $DIR/proc-macro-cannot-be-used.rs:50:28
    |
 LL |     fn trait2(#[id] &self, #[id] arg1: u8);
    |                            ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:50:19
+  --> $DIR/proc-macro-cannot-be-used.rs:53:19
    |
 LL |     fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
    |                   ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:50:39
+  --> $DIR/proc-macro-cannot-be-used.rs:53:39
    |
 LL |     fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
    |                                       ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:53:19
+  --> $DIR/proc-macro-cannot-be-used.rs:56:19
    |
 LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
    |                   ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:53:42
+  --> $DIR/proc-macro-cannot-be-used.rs:56:42
    |
 LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
    |                                          ^^^^^
 
 error: expected an inert attribute, found an attribute macro
-  --> $DIR/proc-macro-cannot-be-used.rs:53:58
+  --> $DIR/proc-macro-cannot-be-used.rs:56:58
    |
 LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
    |                                                          ^^^^^
 
-error: aborting due to 25 previous errors
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:60:38
+   |
+LL |     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
+   |                                      ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:60:54
+   |
+LL |     fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8);
+   |                                                      ^^^^^
+
+error: aborting due to 29 previous errors
 
diff --git a/src/test/ui/struct-literal-variant-in-if.stderr b/src/test/ui/struct-literal-variant-in-if.stderr
index 85cbc787bc2..a52ec6dc539 100644
--- a/src/test/ui/struct-literal-variant-in-if.stderr
+++ b/src/test/ui/struct-literal-variant-in-if.stderr
@@ -50,7 +50,10 @@ error[E0308]: mismatched types
   --> $DIR/struct-literal-variant-in-if.rs:10:20
    |
 LL |     if x == E::V { field } {}
-   |                    ^^^^^ expected (), found bool
+   |     ---------------^^^^^--- help: consider using a semicolon here
+   |     |              |
+   |     |              expected (), found bool
+   |     expected this to be `()`
    |
    = note: expected type `()`
               found type `bool`
diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index 28b331bdbdc..1af0f7a191e 100644
--- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -1,6 +1,9 @@
 error[E0423]: expected value, found struct variant `E::B`
   --> $DIR/fn-or-tuple-struct-without-args.rs:36:16
    |
+LL |     B { a: usize },
+   |     -------------- `E::B` defined here
+...
 LL |     let _: E = E::B;
    |                ^^^-
    |                |  |
diff --git a/src/test/ui/suggestions/issue-61226.stderr b/src/test/ui/suggestions/issue-61226.stderr
index 6d7d98ac6a1..fbcfba6653f 100644
--- a/src/test/ui/suggestions/issue-61226.stderr
+++ b/src/test/ui/suggestions/issue-61226.stderr
@@ -1,6 +1,9 @@
 error[E0423]: expected value, found struct `X`
   --> $DIR/issue-61226.rs:3:10
    |
+LL | struct X {}
+   | ----------- `X` defined here
+LL | fn main() {
 LL |     vec![X]; //…
    |          ^ did you mean `X { /* fields */ }`?
 
diff --git a/src/test/ui/suggestions/match-needing-semi.fixed b/src/test/ui/suggestions/match-needing-semi.fixed
new file mode 100644
index 00000000000..03cbed1376e
--- /dev/null
+++ b/src/test/ui/suggestions/match-needing-semi.fixed
@@ -0,0 +1,18 @@
+// check-only
+// run-rustfix
+
+fn main() {
+    match 3 {
+        4 => 1,
+        3 => {
+            2 //~ ERROR mismatched types
+        }
+        _ => 2
+    };
+    match 3 { //~ ERROR mismatched types
+        4 => 1,
+        3 => 2,
+        _ => 2
+    };
+    let _ = ();
+}
diff --git a/src/test/ui/suggestions/match-needing-semi.rs b/src/test/ui/suggestions/match-needing-semi.rs
new file mode 100644
index 00000000000..f34071ac758
--- /dev/null
+++ b/src/test/ui/suggestions/match-needing-semi.rs
@@ -0,0 +1,18 @@
+// check-only
+// run-rustfix
+
+fn main() {
+    match 3 {
+        4 => 1,
+        3 => {
+            2 //~ ERROR mismatched types
+        }
+        _ => 2
+    }
+    match 3 { //~ ERROR mismatched types
+        4 => 1,
+        3 => 2,
+        _ => 2
+    }
+    let _ = ();
+}
diff --git a/src/test/ui/suggestions/match-needing-semi.stderr b/src/test/ui/suggestions/match-needing-semi.stderr
new file mode 100644
index 00000000000..988945817c2
--- /dev/null
+++ b/src/test/ui/suggestions/match-needing-semi.stderr
@@ -0,0 +1,36 @@
+error[E0308]: mismatched types
+  --> $DIR/match-needing-semi.rs:8:13
+   |
+LL | /     match 3 {
+LL | |         4 => 1,
+LL | |         3 => {
+LL | |             2
+   | |             ^ expected (), found integer
+LL | |         }
+LL | |         _ => 2
+LL | |     }
+   | |     -- help: consider using a semicolon here
+   | |_____|
+   |       expected this to be `()`
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/match-needing-semi.rs:12:5
+   |
+LL | /     match 3 {
+LL | |         4 => 1,
+LL | |         3 => 2,
+LL | |         _ => 2
+LL | |     }
+   | |     ^- help: consider using a semicolon here
+   | |_____|
+   |       expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr
index 128a85e1563..357b33de51b 100644
--- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr
@@ -6,3 +6,4 @@ LL |             Self::A => (),
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0533`.
diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
index c1ea816b7fa..c6528e417d8 100644
--- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
@@ -39,5 +39,5 @@ LL |     let Alias::Unit() = panic!();
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0164, E0618.
+Some errors have detailed explanations: E0164, E0533, E0618.
 For more information about an error, try `rustc --explain E0164`.