diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index d353bc19f7a..eef6d38aa05 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -43,6 +43,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
                 items: BTreeSet::new(),
                 trait_items: BTreeSet::new(),
                 impl_items: BTreeSet::new(),
+                foreign_items: BTreeSet::new(),
             },
         );
 
@@ -105,6 +106,18 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
 
         visit::walk_assoc_item(self, item, ctxt);
     }
+
+    fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
+        self.lctx.allocate_hir_id_counter(item.id);
+        self.lctx.with_hir_id_owner(item.id, |lctx| {
+            let hir_item = lctx.lower_foreign_item(item);
+            let id = hir::ForeignItemId { hir_id: hir_item.hir_id };
+            lctx.foreign_items.insert(id, hir_item);
+            lctx.modules.get_mut(&lctx.current_module).unwrap().foreign_items.insert(id);
+        });
+
+        visit::walk_foreign_item(self, item);
+    }
 }
 
 impl<'hir> LoweringContext<'_, 'hir> {
@@ -304,7 +317,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 })
             }
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
-            ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
+            ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
+                abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
+                items: self
+                    .arena
+                    .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+            },
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
             ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
                 // We lower
@@ -704,10 +722,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod<'hir> {
-        hir::ForeignMod {
-            abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
-            items: self.arena.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item(x))),
+    fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
+        hir::ForeignItemRef {
+            id: hir::ForeignItemId { hir_id: self.lower_node_id(i.id) },
+            ident: i.ident,
+            span: i.span,
+            vis: self.lower_visibility(&i.vis, Some(i.id)),
         }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index eb45a0e1c05..2e1b5a74a7b 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -101,6 +101,7 @@ struct LoweringContext<'a, 'hir: 'a> {
 
     trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem<'hir>>,
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem<'hir>>,
+    foreign_items: BTreeMap<hir::ForeignItemId, hir::ForeignItem<'hir>>,
     bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
     exported_macros: Vec<hir::MacroDef<'hir>>,
     non_exported_macro_attrs: Vec<ast::Attribute>,
@@ -298,6 +299,7 @@ pub fn lower_crate<'a, 'hir>(
         items: BTreeMap::new(),
         trait_items: BTreeMap::new(),
         impl_items: BTreeMap::new(),
+        foreign_items: BTreeMap::new(),
         bodies: BTreeMap::new(),
         trait_impls: BTreeMap::new(),
         modules: BTreeMap::new(),
@@ -485,6 +487,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 visit::walk_assoc_item(self, item, ctxt);
             }
 
+            fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
+                self.lctx.allocate_hir_id_counter(item.id);
+                visit::walk_foreign_item(self, item);
+            }
+
             fn visit_ty(&mut self, t: &'tcx Ty) {
                 match t.kind {
                     // Mirrors the case in visit::walk_ty
@@ -548,6 +555,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             items: self.items,
             trait_items: self.trait_items,
             impl_items: self.impl_items,
+            foreign_items: self.foreign_items,
             bodies: self.bodies,
             body_ids,
             trait_impls: self.trait_impls,
diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs
index 85ab7906d25..44dfdcfccab 100644
--- a/compiler/rustc_hir/src/arena.rs
+++ b/compiler/rustc_hir/src/arena.rs
@@ -29,6 +29,7 @@ macro_rules! arena_types {
             [] field_pat: rustc_hir::FieldPat<$tcx>,
             [] fn_decl: rustc_hir::FnDecl<$tcx>,
             [] foreign_item: rustc_hir::ForeignItem<$tcx>,
+            [few] foreign_item_ref: rustc_hir::ForeignItemRef<$tcx>,
             [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
             [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
             [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 4497c8c0eaa..f01d4417105 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -579,6 +579,7 @@ pub struct ModuleItems {
     pub items: BTreeSet<HirId>,
     pub trait_items: BTreeSet<TraitItemId>,
     pub impl_items: BTreeSet<ImplItemId>,
+    pub foreign_items: BTreeSet<ForeignItemId>,
 }
 
 /// A type representing only the top-level module.
@@ -612,6 +613,7 @@ pub struct Crate<'hir> {
 
     pub trait_items: BTreeMap<TraitItemId, TraitItem<'hir>>,
     pub impl_items: BTreeMap<ImplItemId, ImplItem<'hir>>,
+    pub foreign_items: BTreeMap<ForeignItemId, ForeignItem<'hir>>,
     pub bodies: BTreeMap<BodyId, Body<'hir>>,
     pub trait_impls: BTreeMap<DefId, Vec<HirId>>,
 
@@ -644,6 +646,10 @@ impl Crate<'hir> {
         &self.impl_items[&id]
     }
 
+    pub fn foreign_item(&self, id: ForeignItemId) -> &ForeignItem<'hir> {
+        &self.foreign_items[&id]
+    }
+
     pub fn body(&self, id: BodyId) -> &Body<'hir> {
         &self.bodies[&id]
     }
@@ -673,6 +679,10 @@ impl Crate<'_> {
         for impl_item in self.impl_items.values() {
             visitor.visit_impl_item(impl_item);
         }
+
+        for foreign_item in self.foreign_items.values() {
+            visitor.visit_foreign_item(foreign_item);
+        }
     }
 
     /// A parallel version of `visit_all_item_likes`.
@@ -695,6 +705,11 @@ impl Crate<'_> {
                 par_for_each_in(&self.impl_items, |(_, impl_item)| {
                     visitor.visit_impl_item(impl_item);
                 });
+            },
+            {
+                par_for_each_in(&self.foreign_items, |(_, foreign_item)| {
+                    visitor.visit_foreign_item(foreign_item);
+                });
             }
         );
     }
@@ -1840,7 +1855,7 @@ pub struct FnSig<'hir> {
 }
 
 // The bodies for items are stored "out of line", in a separate
-// hashmap in the `Crate`. Here we just record the node-id of the item
+// hashmap in the `Crate`. Here we just record the hir-id of the item
 // so it can fetched later.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct TraitItemId {
@@ -1884,7 +1899,7 @@ pub enum TraitItemKind<'hir> {
 }
 
 // The bodies for items are stored "out of line", in a separate
-// hashmap in the `Crate`. Here we just record the node-id of the item
+// hashmap in the `Crate`. Here we just record the hir-id of the item
 // so it can fetched later.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct ImplItemId {
@@ -2269,12 +2284,6 @@ pub struct Mod<'hir> {
     pub item_ids: &'hir [ItemId],
 }
 
-#[derive(Debug, HashStable_Generic)]
-pub struct ForeignMod<'hir> {
-    pub abi: Abi,
-    pub items: &'hir [ForeignItem<'hir>],
-}
-
 #[derive(Encodable, Debug, HashStable_Generic)]
 pub struct GlobalAsm {
     pub asm: Symbol,
@@ -2432,7 +2441,7 @@ impl VariantData<'hir> {
 }
 
 // The bodies for items are stored "out of line", in a separate
-// hashmap in the `Crate`. Here we just record the node-id of the item
+// hashmap in the `Crate`. Here we just record the hir-id of the item
 // so it can fetched later.
 #[derive(Copy, Clone, Encodable, Debug)]
 pub struct ItemId {
@@ -2521,7 +2530,7 @@ pub enum ItemKind<'hir> {
     /// A module.
     Mod(Mod<'hir>),
     /// An external module, e.g. `extern { .. }`.
-    ForeignMod(ForeignMod<'hir>),
+    ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] },
     /// Module-level inline assembly (from `global_asm!`).
     GlobalAsm(&'hir GlobalAsm),
     /// A type alias, e.g., `type Foo = Bar<u8>`.
@@ -2614,6 +2623,29 @@ pub enum AssocItemKind {
     Type,
 }
 
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the hir-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
+pub struct ForeignItemId {
+    pub hir_id: HirId,
+}
+
+/// A reference from a foreign block to one of its items. This
+/// contains the item's ID, naturally, but also the item's name and
+/// some other high-level details (like whether it is an associated
+/// type or method, and whether it is public). This allows other
+/// passes to find the impl they want without loading the ID (which
+/// means fewer edges in the incremental compilation graph).
+#[derive(Debug, HashStable_Generic)]
+pub struct ForeignItemRef<'hir> {
+    pub id: ForeignItemId,
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    pub span: Span,
+    pub vis: Visibility<'hir>,
+}
+
 #[derive(Debug, HashStable_Generic)]
 pub struct ForeignItem<'hir> {
     #[stable_hasher(project(name))]
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 35615af0fc7..3e8fc689acf 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -64,6 +64,10 @@ where
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>) {
         self.visitor.visit_impl_item(impl_item);
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>) {
+        self.visitor.visit_foreign_item(foreign_item);
+    }
 }
 
 pub trait IntoVisitor<'hir> {
@@ -88,6 +92,10 @@ where
     fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>) {
         self.0.into_visitor().visit_impl_item(impl_item);
     }
+
+    fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>) {
+        self.0.into_visitor().visit_foreign_item(foreign_item);
+    }
 }
 
 #[derive(Copy, Clone)]
@@ -128,6 +136,7 @@ pub trait Map<'hir> {
     fn item(&self, id: HirId) -> &'hir Item<'hir>;
     fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
+    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
 }
 
 /// An erased version of `Map<'hir>`, using dynamic dispatch.
@@ -150,6 +159,9 @@ impl<'hir> Map<'hir> for ErasedMap<'hir> {
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
         self.0.impl_item(id)
     }
+    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
+        self.0.foreign_item(id)
+    }
 }
 
 /// Specifies what nested things a visitor wants to visit. The most
@@ -277,6 +289,14 @@ pub trait Visitor<'v>: Sized {
         walk_list!(self, visit_impl_item, opt_item);
     }
 
+    /// Like `visit_nested_item()`, but for foreign items. See
+    /// `visit_nested_item()` for advice on when to override this
+    /// method.
+    fn visit_nested_foreign_item(&mut self, id: ForeignItemId) {
+        let opt_item = self.nested_visit_map().inter().map(|map| map.foreign_item(id));
+        walk_list!(self, visit_foreign_item, opt_item);
+    }
+
     /// Invoked to visit the body of a function, method or closure. Like
     /// visit_nested_item, does nothing by default unless you override
     /// `nested_visit_map` to return other than `None`, in which case it will walk
@@ -378,6 +398,9 @@ pub trait Visitor<'v>: Sized {
     fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
         walk_impl_item(self, ii)
     }
+    fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef<'v>) {
+        walk_foreign_item_ref(self, ii)
+    }
     fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) {
         walk_impl_item_ref(self, ii)
     }
@@ -566,9 +589,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             // `visit_mod()` takes care of visiting the `Item`'s `HirId`.
             visitor.visit_mod(module, item.span, item.hir_id)
         }
-        ItemKind::ForeignMod(ref foreign_module) => {
+        ItemKind::ForeignMod { abi: _, items } => {
             visitor.visit_id(item.hir_id);
-            walk_list!(visitor, visit_foreign_item, foreign_module.items);
+            walk_list!(visitor, visit_foreign_item_ref, items);
         }
         ItemKind::GlobalAsm(_) => {
             visitor.visit_id(item.hir_id);
@@ -1012,6 +1035,17 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
     }
 }
 
+pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    foreign_item_ref: &'v ForeignItemRef<'v>,
+) {
+    // N.B., deliberately force a compilation error if/when new fields are added.
+    let ForeignItemRef { id, ident, span: _, ref vis } = *foreign_item_ref;
+    visitor.visit_nested_foreign_item(id);
+    visitor.visit_ident(ident);
+    visitor.visit_vis(vis);
+}
+
 pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref;
diff --git a/compiler/rustc_hir/src/itemlikevisit.rs b/compiler/rustc_hir/src/itemlikevisit.rs
index 369cd49621b..0db562f91a6 100644
--- a/compiler/rustc_hir/src/itemlikevisit.rs
+++ b/compiler/rustc_hir/src/itemlikevisit.rs
@@ -1,4 +1,4 @@
-use super::{ImplItem, Item, TraitItem};
+use super::{ForeignItem, ImplItem, Item, TraitItem};
 
 /// The "item-like visitor" defines only the top-level methods
 /// that can be invoked by `Crate::visit_all_item_likes()`. Whether
@@ -47,6 +47,7 @@ pub trait ItemLikeVisitor<'hir> {
     fn visit_item(&mut self, item: &'hir Item<'hir>);
     fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>);
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>);
+    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>);
 }
 
 /// A parallel variant of `ItemLikeVisitor`.
@@ -54,4 +55,5 @@ pub trait ParItemLikeVisitor<'hir> {
     fn visit_item(&self, item: &'hir Item<'hir>);
     fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>);
     fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>);
+    fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>);
 }
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index 1d3f44a0899..439fb88039b 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -1,8 +1,8 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 
 use crate::hir::{
-    BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty,
-    VisibilityKind,
+    BodyId, Expr, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId,
+    Ty, VisibilityKind,
 };
 use crate::hir_id::{HirId, ItemLocalId};
 use rustc_span::def_id::{DefPathHash, LocalDefId};
@@ -52,6 +52,15 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
     }
 }
 
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        self.hir_id.to_stable_hash_key(hcx)
+    }
+}
+
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for HirId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
         hcx.hash_hir_id(*self, hasher)
@@ -77,6 +86,12 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ItemId {
     }
 }
 
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItemId {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_reference_to_item(self.hir_id, hasher)
+    }
+}
+
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
         hcx.hash_reference_to_item(self.hir_id, hasher)
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index fd6a312ef3a..b870e4c6ead 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -91,7 +91,7 @@ impl Target {
             ItemKind::Const(..) => Target::Const,
             ItemKind::Fn(..) => Target::Fn,
             ItemKind::Mod(..) => Target::Mod,
-            ItemKind::ForeignMod(..) => Target::ForeignMod,
+            ItemKind::ForeignMod { .. } => Target::ForeignMod,
             ItemKind::GlobalAsm(..) => Target::GlobalAsm,
             ItemKind::TyAlias(..) => Target::TyAlias,
             ItemKind::OpaqueTy(..) => Target::OpaqueTy,
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index f7018ae62aa..25b09d76295 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -36,6 +36,7 @@ pub enum Nested {
     Item(hir::ItemId),
     TraitItem(hir::TraitItemId),
     ImplItem(hir::ImplItemId),
+    ForeignItem(hir::ForeignItemId),
     Body(hir::BodyId),
     BodyParamPat(hir::BodyId, usize),
 }
@@ -56,6 +57,7 @@ impl PpAnn for hir::Crate<'_> {
             Nested::Item(id) => state.print_item(self.item(id.id)),
             Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
             Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
+            Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
             Nested::Body(id) => state.print_expr(&self.body(id).value),
             Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat),
         }
@@ -70,6 +72,7 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
             Nested::Item(id) => state.print_item(self.item(id.id)),
             Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
             Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
+            Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
             Nested::Body(id) => state.print_expr(&self.body(id).value),
             Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat),
         }
@@ -349,13 +352,6 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_foreign_mod(&mut self, nmod: &hir::ForeignMod<'_>, attrs: &[ast::Attribute]) {
-        self.print_inner_attributes(attrs);
-        for item in nmod.items {
-            self.print_foreign_item(item);
-        }
-    }
-
     pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) {
         if !lifetime.is_elided() {
             self.print_lifetime(lifetime);
@@ -644,11 +640,14 @@ impl<'a> State<'a> {
                 self.print_mod(_mod, &item.attrs);
                 self.bclose(item.span);
             }
-            hir::ItemKind::ForeignMod(ref nmod) => {
+            hir::ItemKind::ForeignMod { abi, items } => {
                 self.head("extern");
-                self.word_nbsp(nmod.abi.to_string());
+                self.word_nbsp(abi.to_string());
                 self.bopen();
-                self.print_foreign_mod(nmod, &item.attrs);
+                self.print_inner_attributes(item.attrs);
+                for item in items {
+                    self.ann.nested(self, Nested::ForeignItem(item.id));
+                }
                 self.bclose(item.span);
             }
             hir::ItemKind::GlobalAsm(ref ga) => {
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index d55813f4cc5..e1c60050d94 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -280,7 +280,7 @@ impl DirtyCleanVisitor<'tcx> {
                     HirItem::Mod(..) => ("ItemMod", LABELS_HIR_ONLY),
 
                     // // An external module
-                    HirItem::ForeignMod(..) => ("ItemForeignMod", LABELS_HIR_ONLY),
+                    HirItem::ForeignMod { .. } => ("ItemForeignMod", LABELS_HIR_ONLY),
 
                     // Module-level inline assembly (from global_asm!)
                     HirItem::GlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY),
@@ -460,6 +460,10 @@ impl ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> {
     fn visit_impl_item(&mut self, item: &hir::ImplItem<'_>) {
         self.check_item(item.hir_id, item.span);
     }
+
+    fn visit_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
+        self.check_item(item.hir_id, item.span);
+    }
 }
 
 /// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index d56115fd6ac..de08a4c8242 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -33,6 +33,8 @@ impl<'v> ItemLikeVisitor<'v> for Finder<'_> {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs
index 8675197656a..4785b6c379c 100644
--- a/compiler/rustc_metadata/src/foreign_modules.rs
+++ b/compiler/rustc_metadata/src/foreign_modules.rs
@@ -16,13 +16,13 @@ struct Collector<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let fm = match it.kind {
-            hir::ItemKind::ForeignMod(ref fm) => fm,
+        let items = match it.kind {
+            hir::ItemKind::ForeignMod { items, .. } => items,
             _ => return,
         };
 
         let foreign_items =
-            fm.items.iter().map(|it| self.tcx.hir().local_def_id(it.hir_id).to_def_id()).collect();
+            items.iter().map(|it| self.tcx.hir().local_def_id(it.id.hir_id).to_def_id()).collect();
         self.modules.push(ForeignModule {
             foreign_items,
             def_id: self.tcx.hir().local_def_id(it.hir_id).to_def_id(),
@@ -31,4 +31,5 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
 
     fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
 }
diff --git a/compiler/rustc_metadata/src/link_args.rs b/compiler/rustc_metadata/src/link_args.rs
index d8f16796083..d088288c507 100644
--- a/compiler/rustc_metadata/src/link_args.rs
+++ b/compiler/rustc_metadata/src/link_args.rs
@@ -26,11 +26,11 @@ struct Collector<'tcx> {
 
 impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let fm = match it.kind {
-            hir::ItemKind::ForeignMod(ref fm) => fm,
+        let abi = match it.kind {
+            hir::ItemKind::ForeignMod { abi, .. } => abi,
             _ => return,
         };
-        if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
+        if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
             return;
         }
 
@@ -45,6 +45,7 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
 
     fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
 impl<'tcx> Collector<'tcx> {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 2f7c2c2c405..fe29f9d177f 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -33,12 +33,12 @@ struct Collector<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let fm = match it.kind {
-            hir::ItemKind::ForeignMod(ref fm) => fm,
+        let abi = match it.kind {
+            hir::ItemKind::ForeignMod { abi, .. } => abi,
             _ => return,
         };
 
-        if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
+        if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
             return;
         }
 
@@ -127,6 +127,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
 
     fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
 impl Collector<'tcx> {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index a7cf1079b8f..52ffd9a7975 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1225,7 +1225,7 @@ impl EncodeContext<'a, 'tcx> {
             hir::ItemKind::Mod(ref m) => {
                 return self.encode_info_for_mod(item.hir_id, m, &item.attrs);
             }
-            hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
+            hir::ItemKind::ForeignMod { .. } => EntryKind::ForeignMod,
             hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
             hir::ItemKind::TyAlias(..) => EntryKind::Type,
             hir::ItemKind::OpaqueTy(..) => {
@@ -1320,11 +1320,11 @@ impl EncodeContext<'a, 'tcx> {
         record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
         // FIXME(eddyb) there should be a nicer way to do this.
         match item.kind {
-            hir::ItemKind::ForeignMod(ref fm) => record!(self.tables.children[def_id] <-
-                fm.items
+            hir::ItemKind::ForeignMod { items, .. } => record!(self.tables.children[def_id] <-
+                items
                     .iter()
                     .map(|foreign_item| tcx.hir().local_def_id(
-                        foreign_item.hir_id).local_def_index)
+                        foreign_item.id.hir_id).local_def_index)
             ),
             hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
                 self.tcx.adt_def(def_id).variants.iter().map(|v| {
@@ -1836,7 +1836,7 @@ impl EncodeContext<'a, 'tcx> {
             | hir::ItemKind::Const(..)
             | hir::ItemKind::Fn(..)
             | hir::ItemKind::Mod(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..)
             | hir::ItemKind::ExternCrate(..)
             | hir::ItemKind::Use(..)
@@ -1913,6 +1913,8 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
     fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem<'v>) {
         // handled in `visit_item` above
     }
+
+    fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
 }
 
 /// Used to prefetch queries which will be needed later by metadata encoding.
@@ -1977,6 +1979,11 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
             hir::ImplItemKind::TyAlias(..) => (),
         }
     }
+
+    fn visit_foreign_item(&self, _foreign_item: &'v hir::ForeignItem<'v>) {
+        // This should be kept in sync with `encode_info_for_foreign_item`.
+        // Foreign items contain no MIR.
+    }
 }
 
 // NOTE(eddyb) The following comment was preserved for posterity, even
diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs
index 516c9b6752b..912e9672c94 100644
--- a/compiler/rustc_middle/src/hir/map/collector.rs
+++ b/compiler/rustc_middle/src/hir/map/collector.rs
@@ -112,6 +112,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
                 items: _,
                 trait_items: _,
                 impl_items: _,
+                foreign_items: _,
                 bodies: _,
                 trait_impls: _,
                 body_ids: _,
@@ -319,6 +320,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         self.visit_impl_item(self.krate.impl_item(item_id));
     }
 
+    fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
+        self.visit_foreign_item(self.krate.foreign_item(foreign_id));
+    }
+
     fn visit_nested_body(&mut self, id: BodyId) {
         self.visit_body(self.krate.body(id));
     }
@@ -351,11 +356,17 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
-    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>) {
-        self.insert(foreign_item.span, foreign_item.hir_id, Node::ForeignItem(foreign_item));
+    fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
+        debug_assert_eq!(
+            fi.hir_id.owner,
+            self.definitions.opt_hir_id_to_local_def_id(fi.hir_id).unwrap()
+        );
+        self.with_dep_node_owner(fi.hir_id.owner, fi, |this, hash| {
+            this.insert_with_hash(fi.span, fi.hir_id, Node::ForeignItem(fi), hash);
 
-        self.with_parent(foreign_item.hir_id, |this| {
-            intravisit::walk_foreign_item(this, foreign_item);
+            this.with_parent(fi.hir_id, |this| {
+                intravisit::walk_foreign_item(this, fi);
+            });
         });
     }
 
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 37ec3d3d1ca..5e36362ec59 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -205,7 +205,7 @@ impl<'hir> Map<'hir> {
                 ItemKind::TraitAlias(..) => DefKind::TraitAlias,
                 ItemKind::ExternCrate(_) => DefKind::ExternCrate,
                 ItemKind::Use(..) => DefKind::Use,
-                ItemKind::ForeignMod(..) => DefKind::ForeignMod,
+                ItemKind::ForeignMod { .. } => DefKind::ForeignMod,
                 ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
                 ItemKind::Impl { .. } => DefKind::Impl,
             },
@@ -309,6 +309,13 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
+        match self.find(id.hir_id).unwrap() {
+            Node::ForeignItem(item) => item,
+            _ => bug!(),
+        }
+    }
+
     pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
         self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies.get(&id.hir_id.local_id).unwrap()
     }
@@ -470,6 +477,10 @@ impl<'hir> Map<'hir> {
         for id in &module.impl_items {
             visitor.visit_impl_item(self.expect_impl_item(id.hir_id));
         }
+
+        for id in &module.foreign_items {
+            visitor.visit_foreign_item(self.expect_foreign_item(id.hir_id));
+        }
     }
 
     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
@@ -718,10 +729,11 @@ impl<'hir> Map<'hir> {
         let parent = self.get_parent_item(hir_id);
         if let Some(entry) = self.find_entry(parent) {
             if let Entry {
-                node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), ..
+                node: Node::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }),
+                ..
             } = entry
             {
-                return nm.abi;
+                return *abi;
             }
         }
         bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
@@ -937,6 +949,10 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
         self.impl_item(id)
     }
+
+    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
+        self.foreign_item(id)
+    }
 }
 
 trait Named {
@@ -1030,7 +1046,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
                 ItemKind::Const(..) => "const",
                 ItemKind::Fn(..) => "fn",
                 ItemKind::Mod(..) => "mod",
-                ItemKind::ForeignMod(..) => "foreign mod",
+                ItemKind::ForeignMod { .. } => "foreign mod",
                 ItemKind::GlobalAsm(..) => "global asm",
                 ItemKind::TyAlias(..) => "ty",
                 ItemKind::OpaqueTy(..) => "opaque type",
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index a6f90992172..6370ead97e7 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -993,7 +993,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
         match item.kind {
             hir::ItemKind::ExternCrate(..)
             | hir::ItemKind::Use(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::TyAlias(..)
             | hir::ItemKind::Trait(..)
             | hir::ItemKind::TraitAlias(..)
@@ -1066,6 +1066,8 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
             self.push_if_root(def_id);
         }
     }
+
+    fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
 }
 
 impl RootCollector<'_, 'v> {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index f567dd83bc1..b87b13cff80 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -190,7 +190,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
 
                     intravisit::walk_item(self, &item);
                 }
-                hir::ItemKind::ForeignMod(..) => {}
+                hir::ItemKind::ForeignMod { .. } => {}
                 _ => {
                     intravisit::walk_item(self, &item);
                 }
@@ -447,6 +447,8 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
     fn visit_impl_item(&mut self, _item: &hir::ImplItem<'_>) {
         // ignore: we are handling this in `visit_item` above
     }
+
+    fn visit_foreign_item(&mut self, _item: &'v hir::ForeignItem<'v>) {}
 }
 
 fn create_and_seed_worklist<'tcx>(
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 5a087c41f58..699c96bc49d 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -37,6 +37,10 @@ impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> {
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
         self.observe_item(&impl_item.attrs, impl_item.hir_id);
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
+        self.observe_item(foreign_item.attrs, foreign_item.hir_id);
+    }
 }
 
 impl<'tcx> DiagnosticItemCollector<'tcx> {
@@ -100,18 +104,6 @@ fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
 
     // Collect diagnostic items in this crate.
     tcx.hir().krate().visit_all_item_likes(&mut collector);
-    // FIXME(visit_all_item_likes): Foreign items are not visited
-    // here, so we have to manually look at them for now.
-    for (_, foreign_module) in tcx.foreign_modules(LOCAL_CRATE).iter() {
-        for &foreign_item in foreign_module.foreign_items.iter() {
-            match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(foreign_item.expect_local())) {
-                hir::Node::ForeignItem(item) => {
-                    collector.observe_item(item.attrs, item.hir_id);
-                }
-                item => bug!("unexpected foreign item {:?}", item),
-            }
-        }
-    }
 
     for m in tcx.hir().krate().exported_macros {
         collector.observe_item(m.attrs, m.hir_id);
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index e87adb378e7..5ff631a2457 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -2,7 +2,7 @@ use rustc_ast::entry::EntryPointType;
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{CrateNum, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
+use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
@@ -45,6 +45,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
     fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem<'tcx>) {
         // Entry fn is never a trait item.
     }
+
+    fn visit_foreign_item(&mut self, _: &'tcx ForeignItem<'tcx>) {
+        // Entry fn is never a foreign item.
+    }
 }
 
 fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> {
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 6d1a5fcc10b..c7e057927ab 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -68,6 +68,11 @@ impl<'a, 'hir> ItemLikeVisitor<'hir> for OuterVisitor<'a, 'hir> {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
         inner_visitor.check(i.hir_id, |this| intravisit::walk_impl_item(this, i));
     }
+
+    fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) {
+        let mut inner_visitor = self.new_inner_visitor(self.hir_map);
+        inner_visitor.check(i.hir_id, |this| intravisit::walk_foreign_item(this, i));
+    }
 }
 
 impl<'a, 'hir> HirIdValidator<'a, 'hir> {
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 0ae0c381a11..3132661e5f5 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -54,6 +54,8 @@ impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
             impl_item.attrs,
         )
     }
+
+    fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {}
 }
 
 impl LanguageItemCollector<'tcx> {
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 504cbbfcb76..9e83cbd6680 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -40,6 +40,7 @@ impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> {
 
     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
 impl LayoutTest<'tcx> {
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 8d5c980609c..fde83af99a5 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -262,7 +262,7 @@ impl<'tcx> ReachableContext<'tcx> {
                     | hir::ItemKind::TyAlias(..)
                     | hir::ItemKind::Static(..)
                     | hir::ItemKind::Mod(..)
-                    | hir::ItemKind::ForeignMod(..)
+                    | hir::ItemKind::ForeignMod { .. }
                     | hir::ItemKind::Impl { .. }
                     | hir::ItemKind::Trait(..)
                     | hir::ItemKind::TraitAlias(..)
@@ -378,6 +378,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
         // processed in visit_item above
     }
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {
+        // We never export foreign functions as they have no body to export.
+    }
 }
 
 fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> FxHashSet<LocalDefId> {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 04b5c65e464..f6bbbd80bf1 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -326,7 +326,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             // they don't have their own stability. They still can be annotated as unstable
             // and propagate this unstability to children, but this annotation is completely
             // optional. They inherit stability from their parents when unannotated.
-            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {
+            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod { .. } => {
                 self.in_trait_impl = false;
                 kind = AnnotationKind::Container;
             }
@@ -499,7 +499,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
         // optional. They inherit stability from their parents when unannotated.
         if !matches!(
             i.kind,
-            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..)
+            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod { .. }
         ) {
             self.check_missing_stability(i.hir_id, i.span);
         }
diff --git a/compiler/rustc_plugin_impl/src/build.rs b/compiler/rustc_plugin_impl/src/build.rs
index d16dd701a12..4796d9a80b6 100644
--- a/compiler/rustc_plugin_impl/src/build.rs
+++ b/compiler/rustc_plugin_impl/src/build.rs
@@ -25,6 +25,8 @@ impl<'v, 'tcx> ItemLikeVisitor<'v> for RegistrarFinder<'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
 
 /// Finds the function marked with `#[plugin_registrar]`, if any.
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index b8fa9081aa3..4414bf57c6b 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -592,7 +592,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                 Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels)
             }
             // Foreign modules inherit level from parents.
-            hir::ItemKind::ForeignMod(..) => self.prev_level,
+            hir::ItemKind::ForeignMod { .. } => self.prev_level,
             // Other `pub` items inherit levels from parents.
             hir::ItemKind::Const(..)
             | hir::ItemKind::Enum(..)
@@ -654,10 +654,10 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     }
                 }
             }
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for foreign_item in items {
                     if foreign_item.vis.node.is_pub() {
-                        self.update(foreign_item.hir_id, item_level);
+                        self.update(foreign_item.id.hir_id, item_level);
                     }
                 }
             }
@@ -770,11 +770,11 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                 }
             }
             // Visit everything, but foreign items have their own levels.
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
-                    let foreign_item_level = self.get(foreign_item.hir_id);
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for foreign_item in items {
+                    let foreign_item_level = self.get(foreign_item.id.hir_id);
                     if foreign_item_level.is_some() {
-                        self.reach(foreign_item.hir_id, foreign_item_level)
+                        self.reach(foreign_item.id.hir_id, foreign_item_level)
                             .generics()
                             .predicates()
                             .ty();
@@ -1430,7 +1430,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
 
             // An `extern {}` doesn't introduce a new privacy
             // namespace (the contents have their own privacies).
-            hir::ItemKind::ForeignMod(_) => {}
+            hir::ItemKind::ForeignMod { .. } => {}
 
             hir::ItemKind::Trait(.., ref bounds, _) => {
                 if !self.trait_is_public(item.hir_id) {
@@ -1948,10 +1948,10 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
                 }
             }
             // Subitems of foreign modules have their own publicity.
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
-                    let vis = tcx.visibility(tcx.hir().local_def_id(foreign_item.hir_id));
-                    self.check(foreign_item.hir_id, vis).generics().predicates().ty();
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for foreign_item in items {
+                    let vis = tcx.visibility(tcx.hir().local_def_id(foreign_item.id.hir_id));
+                    self.check(foreign_item.id.hir_id, vis).generics().predicates().ty();
                 }
             }
             // Subitems of structs and unions have their own publicity.
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index c79d670737e..91edbebc05f 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -388,7 +388,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             hir::ItemKind::ExternCrate(_)
             | hir::ItemKind::Use(..)
             | hir::ItemKind::Mod(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..) => {
                 // These sorts of items have no lifetime parameters at all.
                 intravisit::walk_item(self, item);
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
index 2f82d0546ba..ff445d727fa 100644
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ b/compiler/rustc_save_analysis/src/sig.rs
@@ -550,7 +550,7 @@ impl<'hir> Sig for hir::Item<'hir> {
 
                 // FIXME where clause
             }
-            hir::ItemKind::ForeignMod(_) => Err("extern mod"),
+            hir::ItemKind::ForeignMod { .. } => Err("extern mod"),
             hir::ItemKind::GlobalAsm(_) => Err("global asm"),
             hir::ItemKind::ExternCrate(_) => Err("extern crate"),
             hir::ItemKind::OpaqueTy(..) => Err("opaque type"),
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index a28c8cac728..8c5e438a728 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -71,4 +71,8 @@ impl hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> {
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         self.process_attrs(impl_item.hir_id);
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
+        self.process_attrs(foreign_item.hir_id);
+    }
 }
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index d5518dfc15a..19957e7d303 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -746,20 +746,22 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
             let generics = tcx.generics_of(def_id);
             check_type_params_are_used(tcx, &generics, pty_ty);
         }
-        hir::ItemKind::ForeignMod(ref m) => {
-            check_abi(tcx, it.span, m.abi);
+        hir::ItemKind::ForeignMod { abi, items } => {
+            check_abi(tcx, it.span, abi);
 
-            if m.abi == Abi::RustIntrinsic {
-                for item in m.items {
+            if abi == Abi::RustIntrinsic {
+                for item in items {
+                    let item = tcx.hir().foreign_item(item.id);
                     intrinsic::check_intrinsic_type(tcx, item);
                 }
-            } else if m.abi == Abi::PlatformIntrinsic {
-                for item in m.items {
+            } else if abi == Abi::PlatformIntrinsic {
+                for item in items {
+                    let item = tcx.hir().foreign_item(item.id);
                     intrinsic::check_platform_intrinsic_type(tcx, item);
                 }
             } else {
-                for item in m.items {
-                    let def_id = tcx.hir().local_def_id(item.hir_id);
+                for item in items {
+                    let def_id = tcx.hir().local_def_id(item.id.hir_id);
                     let generics = tcx.generics_of(def_id);
                     let own_counts = generics.own_counts();
                     if generics.params.len() - own_counts.lifetimes != 0 {
@@ -791,9 +793,10 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                         .emit();
                     }
 
+                    let item = tcx.hir().foreign_item(item.id);
                     match item.kind {
                         hir::ForeignItemKind::Fn(ref fn_decl, _, _) => {
-                            require_c_abi_if_c_variadic(tcx, fn_decl, m.abi, item.span);
+                            require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
                         }
                         hir::ForeignItemKind::Static(..) => {
                             check_static_inhabited(tcx, def_id, item.span);
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index a979bc470d8..7ed2933c08b 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -1308,6 +1308,8 @@ fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
         fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
         fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+
+        fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
     }
 
     tcx.hir().krate().visit_all_item_likes(&mut Visitor { map: &tcx.hir(), traits: &mut traits });
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 1479eadf1b0..d27a68ccf1b 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -1134,6 +1134,7 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
     }
     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
 fn typeck_item_bodies(tcx: TyCtxt<'_>, crate_num: CrateNum) {
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index aeca801a4ee..c09f8cce5b4 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -156,8 +156,9 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         hir::ItemKind::Const(ref ty, ..) => {
             check_item_type(tcx, item.hir_id, ty.span, false);
         }
-        hir::ItemKind::ForeignMod(ref module) => {
-            for it in module.items.iter() {
+        hir::ItemKind::ForeignMod { items, .. } => {
+            for it in items.iter() {
+                let it = tcx.hir().foreign_item(it.id);
                 match it.kind {
                     hir::ForeignItemKind::Fn(ref decl, ..) => {
                         check_item_fn(tcx, it.hir_id, it.ident, it.span, decl)
@@ -1345,6 +1346,10 @@ impl ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
     fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         Visitor::visit_impl_item(&mut self.clone(), impl_item);
     }
+
+    fn visit_foreign_item(&self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
+        Visitor::visit_foreign_item(&mut self.clone(), foreign_item)
+    }
 }
 
 impl Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs
index 4fda8932e21..31121ece898 100644
--- a/compiler/rustc_typeck/src/check_unused.rs
+++ b/compiler/rustc_typeck/src/check_unused.rs
@@ -35,6 +35,8 @@ impl ItemLikeVisitor<'v> for CheckVisitor<'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
 
 struct CheckVisitor<'tcx> {
@@ -225,4 +227,6 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
index 373acb95c9e..483ab2f58f2 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
@@ -334,6 +334,8 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
 
 impl InherentCollect<'tcx> {
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
index ce157f809ef..dd90724e93f 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
@@ -149,4 +149,6 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'v>) {}
 }
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs
index b2009962aba..253dcf06e01 100644
--- a/compiler/rustc_typeck/src/coherence/orphan.rs
+++ b/compiler/rustc_typeck/src/coherence/orphan.rs
@@ -244,4 +244,6 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs
index b281092ea63..2d9128e7dc0 100644
--- a/compiler/rustc_typeck/src/coherence/unsafety.rs
+++ b/compiler/rustc_typeck/src/coherence/unsafety.rs
@@ -94,4 +94,6 @@ impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index dee0e6c2ebb..0ff10abb60a 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -646,8 +646,9 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
         | hir::ItemKind::Use(..)
         | hir::ItemKind::Mod(_)
         | hir::ItemKind::GlobalAsm(_) => {}
-        hir::ItemKind::ForeignMod(ref foreign_mod) => {
-            for item in foreign_mod.items {
+        hir::ItemKind::ForeignMod { items, .. } => {
+            for item in items {
+                let item = tcx.hir().foreign_item(item.id);
                 let def_id = tcx.hir().local_def_id(item.hir_id);
                 tcx.ensure().generics_of(def_id);
                 tcx.ensure().type_of(def_id);
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index c4f4c8bc76b..88ba5788b05 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -259,7 +259,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 ItemKind::Trait(..)
                 | ItemKind::TraitAlias(..)
                 | ItemKind::Mod(..)
-                | ItemKind::ForeignMod(..)
+                | ItemKind::ForeignMod { .. }
                 | ItemKind::GlobalAsm(..)
                 | ItemKind::ExternCrate(..)
                 | ItemKind::Use(..) => {
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs
index 4901d6041d6..14daa97c2c5 100644
--- a/compiler/rustc_typeck/src/impl_wf_check.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check.rs
@@ -93,6 +93,8 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
 fn enforce_impl_params_are_constrained(
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
index e7a9e078a73..3d0635e3fe4 100644
--- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
@@ -109,6 +109,8 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
     fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {}
 
     fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {}
+
+    fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
 fn insert_required_predicates_to_be_wf<'tcx>(
diff --git a/compiler/rustc_typeck/src/outlives/test.rs b/compiler/rustc_typeck/src/outlives/test.rs
index abe9319d71c..56d42f756c4 100644
--- a/compiler/rustc_typeck/src/outlives/test.rs
+++ b/compiler/rustc_typeck/src/outlives/test.rs
@@ -26,4 +26,5 @@ impl ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> {
 
     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs
index b2b062e4095..a8fbdfb7c65 100644
--- a/compiler/rustc_typeck/src/variance/constraints.rs
+++ b/compiler/rustc_typeck/src/variance/constraints.rs
@@ -92,14 +92,6 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
                 self.visit_node_helper(item.hir_id);
             }
 
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
-                    if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
-                        self.visit_node_helper(foreign_item.hir_id);
-                    }
-                }
-            }
-
             _ => {}
         }
     }
@@ -115,6 +107,12 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
             self.visit_node_helper(impl_item.hir_id);
         }
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
+        if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
+            self.visit_node_helper(foreign_item.hir_id);
+        }
+    }
 }
 
 impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
diff --git a/compiler/rustc_typeck/src/variance/terms.rs b/compiler/rustc_typeck/src/variance/terms.rs
index 81c858c53cb..3b2a1c24ddd 100644
--- a/compiler/rustc_typeck/src/variance/terms.rs
+++ b/compiler/rustc_typeck/src/variance/terms.rs
@@ -153,14 +153,6 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
                 self.add_inferreds_for_item(item.hir_id);
             }
 
-            hir::ItemKind::ForeignMod(ref foreign_mod) => {
-                for foreign_item in foreign_mod.items {
-                    if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
-                        self.add_inferreds_for_item(foreign_item.hir_id);
-                    }
-                }
-            }
-
             _ => {}
         }
     }
@@ -176,4 +168,10 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
             self.add_inferreds_for_item(impl_item.hir_id);
         }
     }
+
+    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
+        if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
+            self.add_inferreds_for_item(foreign_item.hir_id);
+        }
+    }
 }
diff --git a/compiler/rustc_typeck/src/variance/test.rs b/compiler/rustc_typeck/src/variance/test.rs
index 1aab89310c6..d6e43b6d669 100644
--- a/compiler/rustc_typeck/src/variance/test.rs
+++ b/compiler/rustc_typeck/src/variance/test.rs
@@ -26,4 +26,5 @@ impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
 
     fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
+    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index e57717dab76..02152edbbc2 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -240,8 +240,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         }
 
         match item.kind {
-            hir::ItemKind::ForeignMod(ref fm) => {
-                for item in fm.items {
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for item in items {
+                    let item = self.cx.tcx.hir().foreign_item(item.id);
                     self.visit_foreign_item(item, None, om);
                 }
             }
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
index 0b9a0fd7945..dd775167757 100644
--- a/src/test/incremental/hashes/extern_mods.rs
+++ b/src/test/incremental/hashes/extern_mods.rs
@@ -13,114 +13,99 @@
 #![feature(rustc_attrs)]
 #![feature(unboxed_closures)]
 #![feature(link_args)]
-#![crate_type="rlib"]
-
+#![crate_type = "rlib"]
 
 // Change function name --------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn change_function_name1(c: i64) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn change_function_name2(c: i64) -> i32;
 }
 
-
-
 // Change parameter name -------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn change_parameter_name(c: i64) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn change_parameter_name(d: i64) -> i32;
 }
 
-
-
 // Change parameter type -------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn change_parameter_type(c: i64) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn change_parameter_type(c: i32) -> i32;
 }
 
-
-
 // Change return type ----------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn change_return_type(c: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn change_return_type(c: i32) -> i8;
 }
 
-
-
 // Add parameter ---------------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn add_parameter(c: i32) -> i32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn add_parameter(c: i32, d: i32) -> i32;
 }
 
-
-
 // Add return type -------------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn add_return_type(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn add_return_type(c: i32) -> i32;
 }
 
-
-
 // Make function variadic ------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn make_function_variadic(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn make_function_variadic(c: i32, ...);
 }
 
-
-
 // Change calling convention ---------------------------------------------------
 #[cfg(cfail1)]
 extern "C" {
@@ -128,74 +113,66 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
 extern "rust-call" {
     pub fn change_calling_convention(c: i32);
 }
 
-
-
 // Make function public --------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     fn make_function_public(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn make_function_public(c: i32);
 }
 
-
-
 // Add function ----------------------------------------------------------------
 #[cfg(cfail1)]
-extern {
+extern "C" {
     pub fn add_function1(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-extern {
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+extern "C" {
     pub fn add_function1(c: i32);
     pub fn add_function2();
 }
 
-
-
 // Change link-args ------------------------------------------------------------
 #[cfg(cfail1)]
 #[link_args = "-foo -bar"]
-extern {
+extern "C" {
     pub fn change_link_args(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
 #[link_args = "-foo -bar -baz"]
-extern {
+extern "C" {
     pub fn change_link_args(c: i32);
 }
 
-
-
 // Change link-name ------------------------------------------------------------
 #[cfg(cfail1)]
 #[link(name = "foo")]
-extern {
+extern "C" {
     pub fn change_link_name(c: i32);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
+#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
 #[link(name = "bar")]
-extern {
+extern "C" {
     pub fn change_link_name(c: i32);
 }
 
@@ -209,15 +186,13 @@ mod indirectly_change_parameter_type {
     #[cfg(not(cfail1))]
     use super::c_i64 as c_int;
 
-    #[rustc_dirty(cfg="cfail2")]
-    #[rustc_clean(cfg="cfail3")]
-    extern {
+    #[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg = "cfail3")]
+    extern "C" {
         pub fn indirectly_change_parameter_type(c: c_int);
     }
 }
 
-
-
 // Indirectly change return type --------------------------------------------
 mod indirectly_change_return_type {
     #[cfg(cfail1)]
@@ -225,9 +200,9 @@ mod indirectly_change_return_type {
     #[cfg(not(cfail1))]
     use super::c_i64 as c_int;
 
-    #[rustc_dirty(cfg="cfail2")]
-    #[rustc_clean(cfg="cfail3")]
-    extern {
+    #[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg = "cfail3")]
+    extern "C" {
         pub fn indirectly_change_return_type() -> c_int;
     }
 }
diff --git a/src/test/ui/asm/naked-invalid-attr.stderr b/src/test/ui/asm/naked-invalid-attr.stderr
index beaa34140c9..565c2986a66 100644
--- a/src/test/ui/asm/naked-invalid-attr.stderr
+++ b/src/test/ui/asm/naked-invalid-attr.stderr
@@ -1,11 +1,3 @@
-error: attribute should be applied to a function definition
-  --> $DIR/naked-invalid-attr.rs:9:5
-   |
-LL |     #[naked]
-   |     ^^^^^^^^
-LL |     fn f();
-   |     ------- not a function definition
-
 error: attribute should be applied to a function definition
   --> $DIR/naked-invalid-attr.rs:13:1
    |
@@ -32,6 +24,14 @@ LL |     #[naked]
 LL |     extern "C" fn invoke(&self);
    |     ---------------------------- not a function definition
 
+error: attribute should be applied to a function definition
+  --> $DIR/naked-invalid-attr.rs:9:5
+   |
+LL |     #[naked]
+   |     ^^^^^^^^
+LL |     fn f();
+   |     ------- not a function definition
+
 error: attribute should be applied to a function definition
   --> $DIR/naked-invalid-attr.rs:6:1
    |
diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.stderr b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
index ae04612a4dd..6ac884c12ce 100644
--- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr
+++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
@@ -1,19 +1,3 @@
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/inline-trait-and-foreign-items.rs:30:5
-   |
-LL |     #[inline]
-   |     ^^^^^^^^^
-LL |     static X: u32;
-   |     -------------- not a function or closure
-
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/inline-trait-and-foreign-items.rs:33:5
-   |
-LL |     #[inline]
-   |     ^^^^^^^^^
-LL |     type T;
-   |     ------- not a function or closure
-
 warning: `#[inline]` is ignored on constants
   --> $DIR/inline-trait-and-foreign-items.rs:7:5
    |
@@ -61,6 +45,22 @@ LL |     #[inline]
 LL |     type U = impl Trait;
    |     -------------------- not a function or closure
 
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/inline-trait-and-foreign-items.rs:30:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+LL |     static X: u32;
+   |     -------------- not a function or closure
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/inline-trait-and-foreign-items.rs:33:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+LL |     type T;
+   |     ------- not a function or closure
+
 error: could not find defining uses
   --> $DIR/inline-trait-and-foreign-items.rs:26:14
    |
diff --git a/src/test/ui/lint/warn-unused-inline-on-fn-prototypes.stderr b/src/test/ui/lint/warn-unused-inline-on-fn-prototypes.stderr
index 843db8ce815..ab19d80e732 100644
--- a/src/test/ui/lint/warn-unused-inline-on-fn-prototypes.stderr
+++ b/src/test/ui/lint/warn-unused-inline-on-fn-prototypes.stderr
@@ -1,5 +1,5 @@
 error: `#[inline]` is ignored on function prototypes
-  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:9:5
+  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:4:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
@@ -11,7 +11,7 @@ LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
 error: `#[inline]` is ignored on function prototypes
-  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:4:5
+  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:9:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 009e3d8937e..4678f6872f3 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
             hir::ItemKind::Union(..) => "a union",
             hir::ItemKind::OpaqueTy(..) => "an existential type",
             hir::ItemKind::ExternCrate(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..)
             | hir::ItemKind::Impl { .. }
             | hir::ItemKind::Use(..) => return,
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 53abe6086ea..913d9daff46 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -125,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
             | hir::ItemKind::Union(..)
             | hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::ExternCrate(..)
-            | hir::ItemKind::ForeignMod(..)
+            | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::Impl { .. }
             | hir::ItemKind::Use(..) => {},
         };
diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
index 4fbfb3be32c..8f0ef9150d4 100644
--- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
@@ -395,7 +395,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
             println!("function of type {:#?}", item_ty);
         },
         hir::ItemKind::Mod(..) => println!("module"),
-        hir::ItemKind::ForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
+        hir::ItemKind::ForeignMod { abi, .. } => println!("foreign module with abi: {}", abi),
         hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm),
         hir::ItemKind::TyAlias(..) => {
             println!("type alias for {:?}", cx.tcx.type_of(did));