diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index 88564647d61f9..7cc045ef34461 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -38,6 +38,7 @@ use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
+use std::convert::TryFrom;
 use std::fmt;
 use std::iter;
 
@@ -2443,10 +2444,10 @@ impl Item {
     }
 }
 
-impl<K: IntoItemKind> Item<K> {
+impl<K: Into<ItemKind>> Item<K> {
     pub fn into_item(self) -> Item {
         let Item { attrs, id, span, vis, ident, kind, tokens } = self;
-        Item { attrs, id, span, vis, ident, kind: kind.into_item_kind(), tokens }
+        Item { attrs, id, span, vis, ident, kind: kind.into(), tokens }
     }
 }
 
@@ -2626,20 +2627,11 @@ impl ItemKind {
     }
 }
 
-pub trait IntoItemKind {
-    fn into_item_kind(self) -> ItemKind;
-}
-
-// FIXME(Centril): These definitions should be unmerged;
-// see https://github.com/rust-lang/rust/pull/69194#discussion_r379899975
-pub type ForeignItem = Item<AssocItemKind>;
-pub type ForeignItemKind = AssocItemKind;
-
 /// Represents associated items.
 /// These include items in `impl` and `trait` definitions.
 pub type AssocItem = Item<AssocItemKind>;
 
-/// Represents non-free item kinds.
+/// Represents associated item kinds.
 ///
 /// The term "provided" in the variants below refers to the item having a default
 /// definition / body. Meanwhile, a "required" item lacks a definition / body.
@@ -2648,16 +2640,14 @@ pub type AssocItem = Item<AssocItemKind>;
 /// means "provided" and conversely `None` means "required".
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum AssocItemKind {
-    /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
+    /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
     /// If `def` is parsed, then the constant is provided, and otherwise required.
     Const(Defaultness, P<Ty>, Option<P<Expr>>),
-    /// A static item (`static FOO: u8`).
-    Static(P<Ty>, Mutability, Option<P<Expr>>),
-    /// A function.
+    /// An associated function.
     Fn(Defaultness, FnSig, Generics, Option<P<Block>>),
-    /// A type.
+    /// An associated type.
     TyAlias(Defaultness, Generics, GenericBounds, Option<P<Ty>>),
-    /// A macro expanding to items.
+    /// A macro expanding to associated items.
     Macro(Mac),
 }
 
@@ -2665,19 +2655,72 @@ impl AssocItemKind {
     pub fn defaultness(&self) -> Defaultness {
         match *self {
             Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def,
-            Self::Macro(..) | Self::Static(..) => Defaultness::Final,
+            Self::Macro(..) => Defaultness::Final,
         }
     }
 }
 
-impl IntoItemKind for AssocItemKind {
-    fn into_item_kind(self) -> ItemKind {
-        match self {
+impl From<AssocItemKind> for ItemKind {
+    fn from(assoc_item_kind: AssocItemKind) -> ItemKind {
+        match assoc_item_kind {
             AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
-            AssocItemKind::Static(a, b, c) => ItemKind::Static(a, b, c),
             AssocItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
             AssocItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
             AssocItemKind::Macro(a) => ItemKind::Mac(a),
         }
     }
 }
+
+impl TryFrom<ItemKind> for AssocItemKind {
+    type Error = ItemKind;
+
+    fn try_from(item_kind: ItemKind) -> Result<AssocItemKind, ItemKind> {
+        Ok(match item_kind {
+            ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
+            ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d),
+            ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d),
+            ItemKind::Mac(a) => AssocItemKind::Macro(a),
+            _ => return Err(item_kind),
+        })
+    }
+}
+
+/// An item in `extern` block.
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum ForeignItemKind {
+    /// A foreign static item (`static FOO: u8`).
+    Static(P<Ty>, Mutability, Option<P<Expr>>),
+    /// A foreign function.
+    Fn(Defaultness, FnSig, Generics, Option<P<Block>>),
+    /// A foreign type.
+    TyAlias(Defaultness, Generics, GenericBounds, Option<P<Ty>>),
+    /// A macro expanding to foreign items.
+    Macro(Mac),
+}
+
+impl From<ForeignItemKind> for ItemKind {
+    fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
+        match foreign_item_kind {
+            ForeignItemKind::Static(a, b, c) => ItemKind::Static(a, b, c),
+            ForeignItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
+            ForeignItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
+            ForeignItemKind::Macro(a) => ItemKind::Mac(a),
+        }
+    }
+}
+
+impl TryFrom<ItemKind> for ForeignItemKind {
+    type Error = ItemKind;
+
+    fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
+        Ok(match item_kind {
+            ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
+            ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d),
+            ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d),
+            ItemKind::Mac(a) => ForeignItemKind::Macro(a),
+            _ => return Err(item_kind),
+        })
+    }
+}
+
+pub type ForeignItem = Item<ForeignItemKind>;
diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs
index 53515cee28119..0638e8e667617 100644
--- a/src/librustc_ast/attr/mod.rs
+++ b/src/librustc_ast/attr/mod.rs
@@ -721,6 +721,6 @@ macro_rules! derive_has_attrs {
 }
 
 derive_has_attrs! {
-    Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::Arm,
+    Item, Expr, Local, ast::AssocItem, ast::ForeignItem, ast::StructField, ast::Arm,
     ast::Field, ast::FieldPat, ast::Variant, ast::Param, GenericParam
 }
diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs
index a9b06f602f629..dedc74eea9279 100644
--- a/src/librustc_ast/mut_visit.rs
+++ b/src/librustc_ast/mut_visit.rs
@@ -936,25 +936,12 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
     visitor: &mut T,
 ) -> SmallVec<[P<AssocItem>; 1]> {
     let Item { id, ident, vis, attrs, kind, span, tokens: _ } = item.deref_mut();
-    walk_nested_item(visitor, id, span, ident, vis, attrs, kind);
-    smallvec![item]
-}
-
-pub fn walk_nested_item(
-    visitor: &mut impl MutVisitor,
-    id: &mut NodeId,
-    span: &mut Span,
-    ident: &mut Ident,
-    vis: &mut Visibility,
-    attrs: &mut Vec<Attribute>,
-    kind: &mut AssocItemKind,
-) {
     visitor.visit_id(id);
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
     visit_attrs(attrs, visitor);
     match kind {
-        AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => {
+        AssocItemKind::Const(_, ty, expr) => {
             visitor.visit_ty(ty);
             visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
@@ -971,6 +958,7 @@ pub fn walk_nested_item(
         AssocItemKind::Macro(mac) => visitor.visit_mac(mac),
     }
     visitor.visit_span(span);
+    smallvec![item]
 }
 
 pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
@@ -1036,7 +1024,28 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
     visitor: &mut T,
 ) -> SmallVec<[P<ForeignItem>; 1]> {
     let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut();
-    walk_nested_item(visitor, id, span, ident, vis, attrs, kind);
+    visitor.visit_id(id);
+    visitor.visit_ident(ident);
+    visitor.visit_vis(vis);
+    visit_attrs(attrs, visitor);
+    match kind {
+        ForeignItemKind::Static(ty, _, expr) => {
+            visitor.visit_ty(ty);
+            visit_opt(expr, |expr| visitor.visit_expr(expr));
+        }
+        ForeignItemKind::Fn(_, sig, generics, body) => {
+            visitor.visit_generics(generics);
+            visit_fn_sig(sig, visitor);
+            visit_opt(body, |body| visitor.visit_block(body));
+        }
+        ForeignItemKind::TyAlias(_, generics, bounds, ty) => {
+            visitor.visit_generics(generics);
+            visit_bounds(bounds, visitor);
+            visit_opt(ty, |ty| visitor.visit_ty(ty));
+        }
+        ForeignItemKind::Macro(mac) => visitor.visit_mac(mac),
+    }
+    visitor.visit_span(span);
     smallvec![item]
 }
 
diff --git a/src/librustc_ast/visit.rs b/src/librustc_ast/visit.rs
index c92a4db6dee0b..1436c84b9c1f3 100644
--- a/src/librustc_ast/visit.rs
+++ b/src/librustc_ast/visit.rs
@@ -526,8 +526,29 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
 }
 
 pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) {
-    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
-    walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign);
+    let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item;
+    visitor.visit_vis(vis);
+    visitor.visit_ident(ident);
+    walk_list!(visitor, visit_attribute, attrs);
+    match kind {
+        ForeignItemKind::Static(ty, _, expr) => {
+            visitor.visit_ty(ty);
+            walk_list!(visitor, visit_expr, expr);
+        }
+        ForeignItemKind::Fn(_, sig, generics, body) => {
+            visitor.visit_generics(generics);
+            let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
+            visitor.visit_fn(kind, span, id);
+        }
+        ForeignItemKind::TyAlias(_, generics, bounds, ty) => {
+            visitor.visit_generics(generics);
+            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_ty, ty);
+        }
+        ForeignItemKind::Macro(mac) => {
+            visitor.visit_mac(mac);
+        }
+    }
 }
 
 pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
@@ -610,31 +631,18 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa
 }
 
 pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) {
-    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
-    walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Assoc(ctxt));
-}
-
-fn walk_nested_item<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    id: NodeId,
-    span: Span,
-    ident: Ident,
-    vis: &'a Visibility,
-    attrs: &'a [Attribute],
-    kind: &'a AssocItemKind,
-    ctxt: FnCtxt,
-) {
+    let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item;
     visitor.visit_vis(vis);
     visitor.visit_ident(ident);
     walk_list!(visitor, visit_attribute, attrs);
     match kind {
-        AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => {
+        AssocItemKind::Const(_, ty, expr) => {
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
         AssocItemKind::Fn(_, sig, generics, body) => {
             visitor.visit_generics(generics);
-            let kind = FnKind::Fn(ctxt, ident, sig, vis, body.as_deref());
+            let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
         AssocItemKind::TyAlias(_, generics, bounds, ty) => {
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 13148d97a67f3..46aad99f13130 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -675,11 +675,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let ty = self.lower_ty(t, ImplTraitContext::disallowed());
                     hir::ForeignItemKind::Static(ty, m)
                 }
-                ForeignItemKind::Const(_, ref t, _) => {
-                    // For recovery purposes.
-                    let ty = self.lower_ty(t, ImplTraitContext::disallowed());
-                    hir::ForeignItemKind::Static(ty, Mutability::Not)
-                }
                 ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
                 ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
             },
@@ -757,8 +752,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let trait_item_def_id = self.resolver.definitions().local_def_id(i.id);
 
         let (generics, kind) = match i.kind {
-            AssocItemKind::Static(ref ty, _, ref default) // Let's pretend this is a `const`.
-            | AssocItemKind::Const(_, ref ty, ref default) => {
+            AssocItemKind::Const(_, ref ty, ref default) => {
                 let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                 let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
                 (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
@@ -800,11 +794,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
         let (kind, has_default) = match &i.kind {
-            AssocItemKind::Static(_, _, default) // Let's pretend this is a `const` for recovery.
-            | AssocItemKind::Const(_, _, default) => {
-                (hir::AssocItemKind::Const, default.is_some())
+            AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()),
+            AssocItemKind::TyAlias(_, _, _, default) => {
+                (hir::AssocItemKind::Type, default.is_some())
             }
-            AssocItemKind::TyAlias(_, _, _, default) => (hir::AssocItemKind::Type, default.is_some()),
             AssocItemKind::Fn(_, sig, _, default) => {
                 (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some())
             }
@@ -824,7 +817,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
 
         let (generics, kind) = match &i.kind {
-            AssocItemKind::Static(ty, _, expr) | AssocItemKind::Const(_, ty, expr) => {
+            AssocItemKind::Const(_, ty, expr) => {
                 let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                 (
                     hir::Generics::empty(),
@@ -892,8 +885,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             vis: self.lower_visibility(&i.vis, Some(i.id)),
             defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */),
             kind: match &i.kind {
-                AssocItemKind::Static(..) // Let's pretend this is a `const` for recovery.
-                | AssocItemKind::Const(..) => hir::AssocItemKind::Const,
+                AssocItemKind::Const(..) => hir::AssocItemKind::Const,
                 AssocItemKind::TyAlias(.., ty) => {
                     match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
                         None => hir::AssocItemKind::Type,
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index 9f04c01bfa8f4..69d5610e01601 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -976,7 +976,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             ForeignItemKind::Static(_, _, body) => {
                 self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
             }
-            ForeignItemKind::Const(..) | ForeignItemKind::Macro(..) => {}
+            ForeignItemKind::Macro(..) => {}
         }
 
         visit::walk_foreign_item(self, fi)
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 05e69d0cfd74e..97c88d4f1d966 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -400,7 +400,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             ast::ForeignItemKind::TyAlias(..) => {
                 gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
             }
-            ast::ForeignItemKind::Macro(..) | ast::ForeignItemKind::Const(..) => {}
+            ast::ForeignItemKind::Macro(..) => {}
         }
 
         visit::walk_foreign_item(self, i)
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index f95c154bb3b5a..b11dda8af731e 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -971,19 +971,7 @@ impl<'a> State<'a> {
     }
 
     crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
-        let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item;
-        self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis);
-    }
-
-    fn print_nested_item_kind(
-        &mut self,
-        id: ast::NodeId,
-        span: Span,
-        ident: ast::Ident,
-        attrs: &[Attribute],
-        kind: &ast::AssocItemKind,
-        vis: &ast::Visibility,
-    ) {
+        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
         self.ann.pre(self, AnnNode::SubItem(id));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(span.lo());
@@ -992,9 +980,6 @@ impl<'a> State<'a> {
             ast::ForeignItemKind::Fn(def, sig, gen, body) => {
                 self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
             }
-            ast::ForeignItemKind::Const(def, ty, body) => {
-                self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
-            }
             ast::ForeignItemKind::Static(ty, mutbl, body) => {
                 let def = ast::Defaultness::Final;
                 self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
@@ -1413,8 +1398,29 @@ impl<'a> State<'a> {
     }
 
     crate fn print_assoc_item(&mut self, item: &ast::AssocItem) {
-        let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item;
-        self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis);
+        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
+        self.ann.pre(self, AnnNode::SubItem(id));
+        self.hardbreak_if_not_bol();
+        self.maybe_print_comment(span.lo());
+        self.print_outer_attributes(attrs);
+        match kind {
+            ast::AssocItemKind::Fn(def, sig, gen, body) => {
+                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
+            }
+            ast::AssocItemKind::Const(def, ty, body) => {
+                self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
+            }
+            ast::AssocItemKind::TyAlias(def, generics, bounds, ty) => {
+                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
+            }
+            ast::AssocItemKind::Macro(m) => {
+                self.print_mac(m);
+                if m.args.need_semicolon() {
+                    self.s.word(";");
+                }
+            }
+        }
+        self.ann.post(self, AnnNode::SubItem(id))
     }
 
     crate fn print_stmt(&mut self, st: &ast::Stmt) {
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index a2c512fda91ba..b16659725db73 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -674,11 +674,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     let item_tok = TokenTree::token(
                         token::Interpolated(Lrc::new(match item {
                             Annotatable::Item(item) => token::NtItem(item),
-                            Annotatable::TraitItem(item)
-                            | Annotatable::ImplItem(item)
-                            | Annotatable::ForeignItem(item) => {
+                            Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => {
                                 token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
                             }
+                            Annotatable::ForeignItem(item) => {
+                                token::NtItem(P(item.and_then(ast::ForeignItem::into_item)))
+                            }
                             Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                             Annotatable::Expr(expr) => token::NtExpr(expr),
                             Annotatable::Arm(..)
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 9bca1d0990159..01dd2f885ff5e 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -24,6 +24,7 @@ use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Symbol};
 
 use log::debug;
+use std::convert::TryFrom;
 use std::mem;
 
 pub(super) type ItemInfo = (Ident, ItemKind);
@@ -650,16 +651,16 @@ impl<'a> Parser<'a> {
     /// Parses associated items.
     fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option<Option<P<AssocItem>>>> {
         Ok(self.parse_item_(req_name)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
-            let kind = match kind {
-                ItemKind::Mac(a) => AssocItemKind::Macro(a),
-                ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d),
-                ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d),
-                ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
-                ItemKind::Static(a, _, b) => {
-                    self.struct_span_err(span, "associated `static` items are not allowed").emit();
-                    AssocItemKind::Const(Defaultness::Final, a, b)
-                }
-                _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
+            let kind = match AssocItemKind::try_from(kind) {
+                Ok(kind) => kind,
+                Err(kind) => match kind {
+                    ItemKind::Static(a, _, b) => {
+                        self.struct_span_err(span, "associated `static` items are not allowed")
+                            .emit();
+                        AssocItemKind::Const(Defaultness::Final, a, b)
+                    }
+                    _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
+                },
             };
             Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
         }))
@@ -836,16 +837,15 @@ impl<'a> Parser<'a> {
     /// Parses a foreign item (one in an `extern { ... }` block).
     pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
         Ok(self.parse_item_(|_| true)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
-            let kind = match kind {
-                ItemKind::Mac(a) => ForeignItemKind::Macro(a),
-                ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d),
-                ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d),
-                ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
-                ItemKind::Const(_, a, b) => {
-                    self.error_on_foreign_const(span, ident);
-                    ForeignItemKind::Static(a, Mutability::Not, b)
-                }
-                _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
+            let kind = match ForeignItemKind::try_from(kind) {
+                Ok(kind) => kind,
+                Err(kind) => match kind {
+                    ItemKind::Const(_, a, b) => {
+                        self.error_on_foreign_const(span, ident);
+                        ForeignItemKind::Static(a, Mutability::Not, b)
+                    }
+                    _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
+                },
             };
             Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
         }))
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 86816fd9f3a2a..43cfe05ac230e 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -826,7 +826,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             ForeignItemKind::Fn(..) => {
                 (Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id)), ValueNS)
             }
-            ForeignItemKind::Static(..) | ForeignItemKind::Const(..) => {
+            ForeignItemKind::Static(..) => {
                 (Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS)
             }
             ForeignItemKind::TyAlias(..) => {
@@ -1251,8 +1251,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         // Add the item to the trait info.
         let item_def_id = self.r.definitions.local_def_id(item.id);
         let (res, ns) = match item.kind {
-            AssocItemKind::Static(..) // Let's pretend it's a `const` for recovery.
-            | AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
+            AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
             AssocItemKind::Fn(_, ref sig, _, _) => {
                 if sig.decl.has_self() {
                     self.r.has_self.insert(item_def_id);
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index 2e687c88941fa..0d276e6861452 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -228,9 +228,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     body.as_deref(),
                 );
             }
-            AssocItemKind::Fn(..) | AssocItemKind::Const(..) | AssocItemKind::Static(..) => {
-                DefPathData::ValueNs(i.ident.name)
-            }
+            AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name),
             AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
             AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id),
         };
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index e5aa9c7d8962a..a3554ea2ee0a3 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -444,7 +444,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                     visit::walk_foreign_item(this, foreign_item);
                 });
             }
-            ForeignItemKind::Const(..) | ForeignItemKind::Static(..) => {
+            ForeignItemKind::Static(..) => {
                 self.with_item_rib(HasGenericParams::No, |this| {
                     visit::walk_foreign_item(this, foreign_item);
                 });
@@ -838,8 +838,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                         for item in trait_items {
                             this.with_trait_items(trait_items, |this| {
                                 match &item.kind {
-                                    AssocItemKind::Static(ty, _, default)
-                                    | AssocItemKind::Const(_, ty, default) => {
+                                    AssocItemKind::Const(_, ty, default) => {
                                         this.visit_ty(ty);
                                         // Only impose the restrictions of `ConstRibKind` for an
                                         // actual constant expression in a provided default.
@@ -1114,7 +1113,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                 for item in impl_items {
                                     use crate::ResolutionError::*;
                                     match &item.kind {
-                                        AssocItemKind::Static(..) | AssocItemKind::Const(..) => {
+                                        AssocItemKind::Const(..) => {
                                             debug!("resolve_implementation AssocItemKind::Const",);
                                             // If this is a trait impl, ensure the const
                                             // exists in trait
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index e8cd5ea832db0..72c962749c8be 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1004,8 +1004,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         self.process_macro_use(trait_item.span);
         let vis_span = trait_item.span.shrink_to_lo();
         match trait_item.kind {
-            ast::AssocItemKind::Static(ref ty, _, ref expr)
-            | ast::AssocItemKind::Const(_, ref ty, ref expr) => {
+            ast::AssocItemKind::Const(_, ref ty, ref expr) => {
                 self.process_assoc_const(
                     trait_item.id,
                     trait_item.ident,
@@ -1075,8 +1074,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
     fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) {
         self.process_macro_use(impl_item.span);
         match impl_item.kind {
-            ast::AssocItemKind::Static(ref ty, _, ref expr)
-            | ast::AssocItemKind::Const(_, ref ty, ref expr) => {
+            ast::AssocItemKind::Const(_, ref ty, ref expr) => {
                 self.process_assoc_const(
                     impl_item.id,
                     impl_item.ident,
@@ -1537,8 +1535,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                     self.visit_ty(&ret_ty);
                 }
             }
-            ast::ForeignItemKind::Const(_, ref ty, _)
-            | ast::ForeignItemKind::Static(ref ty, _, _) => {
+            ast::ForeignItemKind::Static(ref ty, _, _) => {
                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(var_data, DefData, item.span);
                     self.dumper.dump_def(&access, var_data);
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index c68289adb1059..9da8ee548fddd 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -151,8 +151,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ForeignItemKind::Const(_, ref ty, _)
-            | ast::ForeignItemKind::Static(ref ty, _, _) => {
+            ast::ForeignItemKind::Static(ref ty, _, _) => {
                 filter!(self.span_utils, item.ident.span);
 
                 let id = id_from_node_id(item.id, self);
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 32da62adc3c02..a295e1637aa4c 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -795,7 +795,6 @@ impl Sig for ast::ForeignItem {
 
                 Ok(Signature { text: text, defs: defs, refs: vec![] })
             }
-            ast::ForeignItemKind::Const(..) => Err("foreign const"),
             ast::ForeignItemKind::Macro(..) => Err("macro"),
         }
     }