Unrolled build for #154661
Rollup merge of #154661 - CoCo-Japan-pan:impl-restriction-check, r=jhpratt,Urgau

Semantic checks of `impl` restrictions

This PR implements semantic checks for `impl` restrictions proposed in the [Restrictions RFC](https://rust-lang.github.io/rfcs/3323-restrictions.html) (Tracking Issue rust-lang/rust#105077), and linked to a [GSOC idea/proposal](https://github.com/rust-lang/google-summer-of-code/tree/142433eb3b104b2f32bae0b9dfafb78a0a2ac579?tab=readme-ov-file#implementing-impl-and-mut-restrictions).

It lowers the resolved paths of `impl` restrictions from the AST to HIR and into `TraitDef`, and integrates the checks into the coherence phase by extending `check_impl`. As parsing (rust-lang/rust#152943) and path resolution (rust-lang/rust#153556) have already been implemented, this PR provides a working implementation of `impl` restrictions.

r? @Urgau
cc @jhpratt
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 072d480..3939cb1 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -24,8 +24,8 @@
 use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};
 use super::stability::{enabled_names, gate_unstable_abi};
 use super::{
-    AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
-    RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
+    AstOwner, FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext,
+    ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
 };
 
 /// Wraps either IndexVec (during `hir_crate`), which acts like a primary
@@ -540,14 +540,14 @@ fn lower_item_kind(
                 constness,
                 is_auto,
                 safety,
-                // FIXME(impl_restrictions): lower to HIR
-                impl_restriction: _,
+                impl_restriction,
                 ident,
                 generics,
                 bounds,
                 items,
             }) => {
                 let constness = self.lower_constness(*constness);
+                let impl_restriction = self.lower_impl_restriction(impl_restriction);
                 let ident = self.lower_ident(*ident);
                 let (generics, (safety, items, bounds)) = self.lower_generics(
                     generics,
@@ -566,7 +566,16 @@ fn lower_item_kind(
                         (safety, items, bounds)
                     },
                 );
-                hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
+                hir::ItemKind::Trait(
+                    constness,
+                    *is_auto,
+                    safety,
+                    impl_restriction,
+                    ident,
+                    generics,
+                    bounds,
+                    items,
+                )
             }
             ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds }) => {
                 let constness = self.lower_constness(*constness);
@@ -1831,6 +1840,38 @@ pub(super) fn lower_safety(&self, s: Safety, default: hir::Safety) -> hir::Safet
         }
     }
 
+    pub(super) fn lower_impl_restriction(
+        &mut self,
+        r: &ImplRestriction,
+    ) -> &'hir hir::ImplRestriction<'hir> {
+        let kind = match &r.kind {
+            RestrictionKind::Unrestricted => hir::RestrictionKind::Unrestricted,
+            RestrictionKind::Restricted { path, id, shorthand: _ } => {
+                let res = self.resolver.get_partial_res(*id);
+                if let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) {
+                    hir::RestrictionKind::Restricted(self.arena.alloc(hir::Path {
+                        res: did,
+                        segments: self.arena.alloc_from_iter(path.segments.iter().map(|segment| {
+                            self.lower_path_segment(
+                                path.span,
+                                segment,
+                                ParamMode::Explicit,
+                                GenericArgsMode::Err,
+                                ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                                None,
+                            )
+                        })),
+                        span: self.lower_span(path.span),
+                    }))
+                } else {
+                    self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
+                    hir::RestrictionKind::Unrestricted
+                }
+            }
+        };
+        self.arena.alloc(hir::ImplRestriction { kind, span: self.lower_span(r.span) })
+    }
+
     /// Return the pair of the lowered `generics` as `hir::Generics` and the evaluation of `f` with
     /// the carried impl trait definitions and bounds.
     #[instrument(level = "debug", skip(self, f))]
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index b6a9e75..15afa9a 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -4341,13 +4341,14 @@ pub fn is_struct_or_union(&self) -> bool {
                 Constness,
                 IsAuto,
                 Safety,
+                &'hir ImplRestriction<'hir>,
                 Ident,
                 &'hir Generics<'hir>,
                 GenericBounds<'hir>,
                 &'hir [TraitItemId]
             ),
-            ItemKind::Trait(constness, is_auto, safety, ident, generics, bounds, items),
-            (*constness, *is_auto, *safety, *ident, generics, bounds, items);
+            ItemKind::Trait(constness, is_auto, safety, impl_restriction, ident, generics, bounds, items),
+            (*constness, *is_auto, *safety, impl_restriction, *ident, generics, bounds, items);
 
         expect_trait_alias, (Constness, Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
             ItemKind::TraitAlias(constness, ident, generics, bounds), (*constness, *ident, generics, bounds);
@@ -4416,6 +4417,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub struct ImplRestriction<'hir> {
+    pub kind: RestrictionKind<'hir>,
+    pub span: Span,
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub enum RestrictionKind<'hir> {
+    /// The restriction does not affect the item.
+    Unrestricted,
+    /// The restriction only applies outside of this path.
+    Restricted(&'hir Path<'hir, DefId>),
+}
+
 /// The actual safety specified in syntax. We may treat
 /// its safety different within the type system to create a
 /// "sound by default" system that needs checking this enum
@@ -4528,6 +4543,7 @@ pub enum ItemKind<'hir> {
         Constness,
         IsAuto,
         Safety,
+        &'hir ImplRestriction<'hir>,
         Ident,
         &'hir Generics<'hir>,
         GenericBounds<'hir>,
@@ -4578,7 +4594,7 @@ pub fn ident(&self) -> Option<Ident> {
             | ItemKind::Enum(ident, ..)
             | ItemKind::Struct(ident, ..)
             | ItemKind::Union(ident, ..)
-            | ItemKind::Trait(_, _, _, ident, ..)
+            | ItemKind::Trait(_, _, _, _, ident, ..)
             | ItemKind::TraitAlias(_, ident, ..) => Some(ident),
 
             ItemKind::Use(_, UseKind::Glob | UseKind::ListStem)
@@ -4596,7 +4612,7 @@ pub fn generics(&self) -> Option<&Generics<'_>> {
             | ItemKind::Enum(_, generics, _)
             | ItemKind::Struct(_, generics, _)
             | ItemKind::Union(_, generics, _)
-            | ItemKind::Trait(_, _, _, _, generics, _, _)
+            | ItemKind::Trait(_, _, _, _, _, generics, _, _)
             | ItemKind::TraitAlias(_, _, generics, _)
             | ItemKind::Impl(Impl { generics, .. }) => generics,
             _ => return None,
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index fab24df..9ffcd34 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -632,11 +632,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
             _constness,
             _is_auto,
             _safety,
+            ref impl_restriction,
             ident,
             ref generics,
             bounds,
             trait_item_refs,
         ) => {
+            if let RestrictionKind::Restricted(path) = &impl_restriction.kind {
+                walk_list!(visitor, visit_path_segment, path.segments);
+            }
             try_visit!(visitor.visit_ident(ident));
             try_visit!(visitor.visit_generics(generics));
             walk_list!(visitor, visit_param_bound, bounds);
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 8f83761..261be88 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -100,6 +100,14 @@ fn enforce_trait_manually_implementable(
             return Err(tcx.dcx().emit_err(errors::SpecializationTrait { span: impl_header_span }));
         }
     }
+
+    if !trait_def.impl_restriction.is_allowed_in(impl_def_id.to_def_id(), tcx) {
+        return Err(tcx.dcx().emit_err(errors::ImplOfRestrictedTrait {
+            impl_span: impl_header_span,
+            restriction_span: trait_def.impl_restriction.expect_span(),
+            restriction_path: trait_def.impl_restriction.restriction_path(tcx),
+        }));
+    }
     Ok(())
 }
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index cfda030..91f6c1a 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -893,11 +893,25 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
 fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
     let item = tcx.hir_expect_item(def_id);
 
-    let (constness, is_alias, is_auto, safety) = match item.kind {
-        hir::ItemKind::Trait(constness, is_auto, safety, ..) => {
-            (constness, false, is_auto == hir::IsAuto::Yes, safety)
-        }
-        hir::ItemKind::TraitAlias(constness, ..) => (constness, true, false, hir::Safety::Safe),
+    let (constness, is_alias, is_auto, safety, impl_restriction) = match item.kind {
+        hir::ItemKind::Trait(constness, is_auto, safety, impl_restriction, ..) => (
+            constness,
+            false,
+            is_auto == hir::IsAuto::Yes,
+            safety,
+            if let hir::RestrictionKind::Restricted(path) = impl_restriction.kind {
+                ty::trait_def::ImplRestrictionKind::Restricted(path.res, impl_restriction.span)
+            } else {
+                ty::trait_def::ImplRestrictionKind::Unrestricted
+            },
+        ),
+        hir::ItemKind::TraitAlias(constness, ..) => (
+            constness,
+            true,
+            false,
+            hir::Safety::Safe,
+            ty::trait_def::ImplRestrictionKind::Unrestricted,
+        ),
         _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
     };
 
@@ -946,6 +960,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
         def_id: def_id.to_def_id(),
         safety,
         constness,
+        impl_restriction,
         paren_sugar,
         has_auto_impl: is_auto,
         is_marker,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 30b1bf4..3c02141 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -165,7 +165,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                         Some(ty::Binder::dummy(tcx.impl_trait_ref(def_id).instantiate_identity()));
                 }
             }
-            ItemKind::Trait(_, _, _, _, _, self_bounds, ..)
+            ItemKind::Trait(_, _, _, _, _, _, self_bounds, ..)
             | ItemKind::TraitAlias(_, _, _, self_bounds) => {
                 is_trait = Some((self_bounds, item.span));
             }
@@ -1038,7 +1038,7 @@ pub(super) fn const_conditions<'tcx>(
         Node::Item(item) => match item.kind {
             hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
             hir::ItemKind::Fn { generics, .. } => (generics, None, false),
-            hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
+            hir::ItemKind::Trait(_, _, _, _, _, generics, supertraits, _) => {
                 (generics, Some((Some(item.owner_id.def_id), supertraits)), false)
             }
             hir::ItemKind::TraitAlias(_, _, generics, supertraits) => {
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 4312d5f..eeaf56a 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -645,7 +645,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             | hir::ItemKind::Enum(_, generics, _)
             | hir::ItemKind::Struct(_, generics, _)
             | hir::ItemKind::Union(_, generics, _)
-            | hir::ItemKind::Trait(_, _, _, _, generics, ..)
+            | hir::ItemKind::Trait(_, _, _, _, _, generics, ..)
             | hir::ItemKind::TraitAlias(_, _, generics, ..)
             | hir::ItemKind::Impl(hir::Impl { generics, .. }) => {
                 // These kinds of items have only early-bound lifetime parameters.
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index c55b9e3..1abafd4 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1036,6 +1036,16 @@ pub(crate) struct SpecializationTrait {
 }
 
 #[derive(Diagnostic)]
+#[diag("trait cannot be implemented outside `{$restriction_path}`")]
+pub(crate) struct ImplOfRestrictedTrait {
+    #[primary_span]
+    pub impl_span: Span,
+    #[note("trait restricted here")]
+    pub restriction_span: Span,
+    pub restriction_path: String,
+}
+
+#[derive(Diagnostic)]
 #[diag("implicit types in closure signatures are forbidden when `for<...>` is present")]
 pub(crate) struct ClosureImplicitHrtb {
     #[primary_span]
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 82540a9..6f64d07 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -761,6 +761,7 @@ fn print_item(&mut self, item: &hir::Item<'_>) {
                 constness,
                 is_auto,
                 safety,
+                impl_restriction,
                 ident,
                 generics,
                 bounds,
@@ -770,6 +771,7 @@ fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.print_constness(constness);
                 self.print_is_auto(is_auto);
                 self.print_safety(safety);
+                self.print_impl_restriction(impl_restriction);
                 self.word_nbsp("trait");
                 self.print_ident(ident);
                 self.print_generic_params(generics.params);
@@ -2645,6 +2647,18 @@ fn print_is_auto(&mut self, s: hir::IsAuto) {
             hir::IsAuto::No => {}
         }
     }
+
+    fn print_impl_restriction(&mut self, r: &hir::ImplRestriction<'_>) {
+        match r.kind {
+            hir::RestrictionKind::Unrestricted => {}
+            hir::RestrictionKind::Restricted(path) => {
+                self.word("impl(");
+                self.word_nbsp("in");
+                self.print_path(path, false);
+                self.word(")");
+            }
+        }
+    }
 }
 
 /// Does this expression require a semicolon to be treated
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index dc5e782..fa90c0c 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1898,7 +1898,7 @@ fn handle_unsatisfied_predicates(
                 Some(
                     Node::Item(hir::Item {
                         kind:
-                            hir::ItemKind::Trait(_, _, _, ident, ..)
+                            hir::ItemKind::Trait(_, _, _, _, ident, ..)
                             | hir::ItemKind::TraitAlias(_, ident, ..),
                         ..
                     })
@@ -4545,7 +4545,7 @@ enum Introducer {
                             return;
                         }
                         Node::Item(hir::Item {
-                            kind: hir::ItemKind::Trait(_, _, _, ident, _, bounds, _),
+                            kind: hir::ItemKind::Trait(_, _, _, _, ident, _, bounds, _),
                             ..
                         }) => {
                             let (sp, sep, article) = if bounds.is_empty() {
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
index 93f067d..9177e00 100644
--- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -39,7 +39,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         let def_id = item.owner_id.to_def_id();
         // NOTE(nbdd0121): use `dyn_compatibility_violations` instead of `is_dyn_compatible` because
         // the latter will report `where_clause_object_safety` lint.
-        if let hir::ItemKind::Trait(_, _, _, ident, ..) = item.kind
+        if let hir::ItemKind::Trait(_, _, _, _, ident, ..) = item.kind
             && cx.tcx.is_dyn_compatible(def_id)
         {
             let direct_super_traits_iter = cx
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 450b9d6..6e82d1c 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -946,7 +946,7 @@ fn named_span(item_span: Span, ident: Ident, generics: Option<&Generics<'_>>) ->
             }) => until_within(*outer_span, ty.span),
             // With generics and bounds.
             Node::Item(Item {
-                kind: ItemKind::Trait(_, _, _, _, generics, bounds, _),
+                kind: ItemKind::Trait(_, _, _, _, _, generics, bounds, _),
                 span: outer_span,
                 ..
             })
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 3e69eda..af5d81a 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -12,6 +12,7 @@
 use crate::query::LocalCrate;
 use crate::traits::specialization_graph;
 use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
+use crate::ty::print::{with_crate_prefix, with_no_trimmed_paths};
 use crate::ty::{Ident, Ty, TyCtxt};
 
 /// A trait's definition with type information.
@@ -24,6 +25,9 @@ pub struct TraitDef {
     /// Whether this trait is `const`.
     pub constness: hir::Constness,
 
+    /// Restrictions on trait implementations.
+    pub impl_restriction: ImplRestrictionKind,
+
     /// If `true`, then this trait had the `#[rustc_paren_sugar]`
     /// attribute, indicating that it should be used with `Foo()`
     /// sugar. This is a temporary thing -- eventually any trait will
@@ -97,6 +101,52 @@ pub enum TraitSpecializationKind {
     AlwaysApplicable,
 }
 
+/// Whether the trait implementation is unrestricted or restricted within a specific module.
+#[derive(HashStable, PartialEq, Clone, Copy, Encodable, Decodable)]
+pub enum ImplRestrictionKind {
+    /// The restriction does not affect this trait, and it can be implemented anywhere.
+    Unrestricted,
+    /// This trait can only be implemented within the specified module.
+    Restricted(DefId, Span),
+}
+
+impl ImplRestrictionKind {
+    /// Returns `true` if the behavior is allowed/unrestricted in the given module.
+    /// A value of `false` indicates that the behavior is prohibited.
+    pub fn is_allowed_in(self, module: DefId, tcx: TyCtxt<'_>) -> bool {
+        match self {
+            ImplRestrictionKind::Unrestricted => true,
+            ImplRestrictionKind::Restricted(restricted_to, _) => {
+                tcx.is_descendant_of(module, restricted_to)
+            }
+        }
+    }
+
+    /// Obtain the [`Span`] of the restriction. Panics if the restriction is unrestricted.
+    pub fn expect_span(self) -> Span {
+        match self {
+            ImplRestrictionKind::Unrestricted => {
+                bug!("called `expect_span` on an unrestricted item")
+            }
+            ImplRestrictionKind::Restricted(_, span) => span,
+        }
+    }
+
+    /// Obtain the path of the restriction. If unrestricted, an empty string is returned.
+    pub fn restriction_path(self, tcx: TyCtxt<'_>) -> String {
+        match self {
+            ImplRestrictionKind::Unrestricted => String::new(),
+            ImplRestrictionKind::Restricted(restricted_to, _) => {
+                if restricted_to.krate == rustc_hir::def_id::LOCAL_CRATE {
+                    with_crate_prefix!(with_no_trimmed_paths!(tcx.def_path_str(restricted_to)))
+                } else {
+                    tcx.def_path_str(restricted_to.krate.as_mod_def_id())
+                }
+            }
+        }
+    }
+}
+
 #[derive(Default, Debug, HashStable)]
 pub struct TraitImpls {
     blanket_impls: Vec<DefId>,
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 896e9d0..54d34ef 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -616,7 +616,7 @@ fn check_diagnostic_on_unimplemented(
 
         if let Some(directive) = directive {
             if let Node::Item(Item {
-                kind: ItemKind::Trait(_, _, _, trait_name, generics, _, _),
+                kind: ItemKind::Trait(_, _, _, _, trait_name, generics, _, _),
                 ..
             }) = self.tcx.hir_node(hir_id)
             {
@@ -1069,7 +1069,7 @@ fn check_doc_search_unbox(&self, span: Span, hir_id: HirId) {
         match item.kind {
             ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _)
                 if generics.params.len() != 0 => {}
-            ItemKind::Trait(_, _, _, _, generics, _, items)
+            ItemKind::Trait(_, _, _, _, _, generics, _, items)
                 if generics.params.len() != 0
                     || items.iter().any(|item| {
                         matches!(self.tcx.def_kind(item.owner_id), DefKind::AssocTy)
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index 69afa4f..0b80666 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -577,7 +577,7 @@ pub fn report_dyn_incompatibility<'tcx>(
     let trait_str = tcx.def_path_str(trait_def_id);
     let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node {
         hir::Node::Item(item) => match item.kind {
-            hir::ItemKind::Trait(_, _, _, ident, ..)
+            hir::ItemKind::Trait(_, _, _, _, ident, ..)
             | hir::ItemKind::TraitAlias(_, ident, _, _) => Some(ident.span),
             _ => unreachable!(),
         },
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index e4689e3..62f6b87 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -484,7 +484,7 @@ pub fn suggest_restricting_param_bound(
             let node = self.tcx.hir_node_by_def_id(body_id);
             match node {
                 hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, _, ident, generics, bounds, _),
+                    kind: hir::ItemKind::Trait(_, _, _, _, ident, generics, bounds, _),
                     ..
                 }) if self_ty == self.tcx.types.self_param => {
                     assert!(param_ty);
@@ -547,7 +547,7 @@ pub fn suggest_restricting_param_bound(
                 }
                 hir::Node::Item(hir::Item {
                     kind:
-                        hir::ItemKind::Trait(_, _, _, _, generics, ..)
+                        hir::ItemKind::Trait(_, _, _, _, _, generics, ..)
                         | hir::ItemKind::Impl(hir::Impl { generics, .. }),
                     ..
                 }) if projection.is_some() => {
@@ -571,7 +571,7 @@ pub fn suggest_restricting_param_bound(
                         hir::ItemKind::Struct(_, generics, _)
                         | hir::ItemKind::Enum(_, generics, _)
                         | hir::ItemKind::Union(_, generics, _)
-                        | hir::ItemKind::Trait(_, _, _, _, generics, ..)
+                        | hir::ItemKind::Trait(_, _, _, _, _, generics, ..)
                         | hir::ItemKind::Impl(hir::Impl { generics, .. })
                         | hir::ItemKind::Fn { generics, .. }
                         | hir::ItemKind::TyAlias(_, generics, _)
@@ -651,7 +651,7 @@ pub fn suggest_restricting_param_bound(
                         hir::ItemKind::Struct(_, generics, _)
                         | hir::ItemKind::Enum(_, generics, _)
                         | hir::ItemKind::Union(_, generics, _)
-                        | hir::ItemKind::Trait(_, _, _, _, generics, ..)
+                        | hir::ItemKind::Trait(_, _, _, _, _, generics, ..)
                         | hir::ItemKind::Impl(hir::Impl { generics, .. })
                         | hir::ItemKind::Fn { generics, .. }
                         | hir::ItemKind::TyAlias(_, generics, _)
@@ -3831,7 +3831,7 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
                 let mut is_auto_trait = false;
                 match tcx.hir_get_if_local(data.impl_or_alias_def_id) {
                     Some(Node::Item(hir::Item {
-                        kind: hir::ItemKind::Trait(_, is_auto, _, ident, ..),
+                        kind: hir::ItemKind::Trait(_, is_auto, _, _, ident, _, _, _),
                         ..
                     })) => {
                         // FIXME: we should do something else so that it works even on crate foreign
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 042c17c..a8e742f 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -609,7 +609,7 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
                     match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.scope))
                     {
                         hir::Node::Item(hir::Item {
-                            kind: hir::ItemKind::Trait(_, _, _, _, generics, ..),
+                            kind: hir::ItemKind::Trait(_, _, _, _, _, generics, ..),
                             ..
                         })
                         | hir::Node::Item(hir::Item {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9e8fc2e..5fa5c7b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2914,7 +2914,8 @@ fn get_name(tcx: TyCtxt<'_>, item: &hir::Item<'_>, renamed: Option<Symbol>) -> O
             ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
                 clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
             }
-            ItemKind::Trait(_, _, _, _, generics, bounds, item_ids) => {
+            // FIXME: rustdoc will need to handle `impl` restrictions at some point
+            ItemKind::Trait(_, _, _, _impl_restriction, _, generics, bounds, item_ids) => {
                 let items = item_ids
                     .iter()
                     .map(|&ti| clean_trait_item(cx.tcx.hir_trait_item(ti), cx))
diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
index 454026e..7f0f0a0 100644
--- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
+++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
@@ -306,7 +306,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
                     cur_f = Some(field);
                 }
             },
-            ItemKind::Trait(_constness, is_auto, _safety, _ident, _generics, _generic_bounds, item_ref)
+            ItemKind::Trait(_constness, is_auto, _safety, _impl_restriction, _ident, _generics, _generic_bounds, item_ref)
                 if self.enable_ordering_for_trait && *is_auto == IsAuto::No =>
             {
                 let mut cur_t: Option<(TraitItemId, Ident)> = None;
diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index 70df856..06bea4b 100644
--- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -528,7 +528,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
             | ItemKind::Fn { ident, .. }
             | ItemKind::Macro(ident, ..)
             | ItemKind::Static(_, ident, ..)
-            | ItemKind::Trait(_, _, _, ident, ..)
+            | ItemKind::Trait(_, _, _, _, ident, ..)
             | ItemKind::TraitAlias(_, ident, ..)
             | ItemKind::TyAlias(ident, ..)
             | ItemKind::Union(ident, ..)
diff --git a/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs b/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs
index ae53bd6..60dbd6c 100644
--- a/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs
@@ -44,7 +44,7 @@
 
 impl<'tcx> LateLintPass<'tcx> for LenWithoutIsEmpty {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Trait(_, _, _, ident, _, _, trait_items) = item.kind
+        if let ItemKind::Trait(_, _, _, _, ident, _, _, trait_items) = item.kind
             && !item.span.from_expansion()
         {
             check_trait_items(cx, item, ident, trait_items);
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 89a6129..35e75d3 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -159,7 +159,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
             | ItemKind::Macro(ident, ..)
             | ItemKind::Static(_, ident, ..)
             | ItemKind::Struct(ident, ..)
-            | ItemKind::Trait(_, _, _, ident, ..)
+            | ItemKind::Trait(_, _, _, _, ident, ..)
             | ItemKind::TraitAlias(_, ident, ..)
             | ItemKind::TyAlias(ident, ..)
             | ItemKind::Union(ident, ..) => ident.span,
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index e7a7852..4cd3707 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -115,7 +115,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         // special handling for self trait bounds as these are not considered generics
         // i.e. trait Foo: Display {}
         if let Item {
-            kind: ItemKind::Trait(_, _, _, _, _, bounds, ..),
+            kind: ItemKind::Trait(_, _, _, _, _, _, bounds, ..),
             ..
         } = item
         {
@@ -136,7 +136,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tc
                     ..
                 }) = segments.first()
                 && let Some(Node::Item(Item {
-                    kind: ItemKind::Trait(_, _, _, _, _, self_bounds, _),
+                    kind: ItemKind::Trait(_, _, _, _, _, _, self_bounds, _),
                     ..
                 })) = cx.tcx.hir_get_if_local(*def_id)
             {
diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
index 6ea6a0a..52dfcab 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -131,7 +131,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) {
             return;
         }
         match it.kind {
-            ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, _, ident, ..) => {
+            ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, _, _, ident, ..) => {
                 check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive);
             },
             ItemKind::Enum(ident, _, ref enumdef) => {
diff --git a/tests/ui/impl-restriction/auxiliary/external-impl-restriction.rs b/tests/ui/impl-restriction/auxiliary/external-impl-restriction.rs
new file mode 100644
index 0000000..785aeed
--- /dev/null
+++ b/tests/ui/impl-restriction/auxiliary/external-impl-restriction.rs
@@ -0,0 +1,8 @@
+#![feature(impl_restriction)]
+#![expect(incomplete_features)]
+
+pub impl(crate) trait TopLevel {}
+
+pub mod inner {
+    pub impl(self) trait Inner {}
+}
diff --git a/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr b/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr
new file mode 100644
index 0000000..402464f
--- /dev/null
+++ b/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr
@@ -0,0 +1,98 @@
+error: trait cannot be implemented outside `external`
+  --> $DIR/impl-restriction-check.rs:12:1
+   |
+LL | impl external::TopLevel for LocalType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/auxiliary/external-impl-restriction.rs:4:5
+   |
+LL | pub impl(crate) trait TopLevel {}
+   |     ^^^^^^^^^^^
+
+error: trait cannot be implemented outside `external`
+  --> $DIR/impl-restriction-check.rs:13:1
+   |
+LL | impl external::inner::Inner for LocalType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/auxiliary/external-impl-restriction.rs:7:9
+   |
+LL |     pub impl(self) trait Inner {}
+   |         ^^^^^^^^^^
+
+error: trait cannot be implemented outside `foo::bar`
+  --> $DIR/impl-restriction-check.rs:30:5
+   |
+LL |     impl bar::Foo for i8 {}
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:17:20
+   |
+LL |         pub(crate) impl(self) trait Foo {}
+   |                    ^^^^^^^^^^
+
+error: trait cannot be implemented outside `foo::bar`
+  --> $DIR/impl-restriction-check.rs:39:1
+   |
+LL | impl foo::bar::Foo for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:17:20
+   |
+LL |         pub(crate) impl(self) trait Foo {}
+   |                    ^^^^^^^^^^
+
+error: trait cannot be implemented outside `foo`
+  --> $DIR/impl-restriction-check.rs:41:1
+   |
+LL | impl foo::bar::Bar for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:18:20
+   |
+LL |         pub(crate) impl(super) trait Bar {}
+   |                    ^^^^^^^^^^^
+
+error: trait cannot be implemented outside `foo::bar`
+  --> $DIR/impl-restriction-check.rs:34:5
+   |
+LL |     impl bar::Qux for i8 {}
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:20:20
+   |
+LL |         pub(crate) impl(in crate::foo::bar) trait Qux {}
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait cannot be implemented outside `foo::bar`
+  --> $DIR/impl-restriction-check.rs:44:1
+   |
+LL | impl foo::bar::Qux for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:20:20
+   |
+LL |         pub(crate) impl(in crate::foo::bar) trait Qux {}
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait cannot be implemented outside `foo`
+  --> $DIR/impl-restriction-check.rs:46:1
+   |
+LL | impl foo::bar::FooBar for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:21:20
+   |
+LL |         pub(crate) impl(in crate::foo) trait FooBar {}
+   |                    ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr b/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr
new file mode 100644
index 0000000..8bd256c
--- /dev/null
+++ b/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr
@@ -0,0 +1,98 @@
+error: trait cannot be implemented outside `external`
+  --> $DIR/impl-restriction-check.rs:12:1
+   |
+LL | impl external::TopLevel for LocalType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/auxiliary/external-impl-restriction.rs:4:5
+   |
+LL | pub impl(crate) trait TopLevel {}
+   |     ^^^^^^^^^^^
+
+error: trait cannot be implemented outside `external`
+  --> $DIR/impl-restriction-check.rs:13:1
+   |
+LL | impl external::inner::Inner for LocalType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/auxiliary/external-impl-restriction.rs:7:9
+   |
+LL |     pub impl(self) trait Inner {}
+   |         ^^^^^^^^^^
+
+error: trait cannot be implemented outside `crate::foo::bar`
+  --> $DIR/impl-restriction-check.rs:30:5
+   |
+LL |     impl bar::Foo for i8 {}
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:17:20
+   |
+LL |         pub(crate) impl(self) trait Foo {}
+   |                    ^^^^^^^^^^
+
+error: trait cannot be implemented outside `crate::foo::bar`
+  --> $DIR/impl-restriction-check.rs:39:1
+   |
+LL | impl foo::bar::Foo for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:17:20
+   |
+LL |         pub(crate) impl(self) trait Foo {}
+   |                    ^^^^^^^^^^
+
+error: trait cannot be implemented outside `crate::foo`
+  --> $DIR/impl-restriction-check.rs:41:1
+   |
+LL | impl foo::bar::Bar for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:18:20
+   |
+LL |         pub(crate) impl(super) trait Bar {}
+   |                    ^^^^^^^^^^^
+
+error: trait cannot be implemented outside `crate::foo::bar`
+  --> $DIR/impl-restriction-check.rs:34:5
+   |
+LL |     impl bar::Qux for i8 {}
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:20:20
+   |
+LL |         pub(crate) impl(in crate::foo::bar) trait Qux {}
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait cannot be implemented outside `crate::foo::bar`
+  --> $DIR/impl-restriction-check.rs:44:1
+   |
+LL | impl foo::bar::Qux for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:20:20
+   |
+LL |         pub(crate) impl(in crate::foo::bar) trait Qux {}
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait cannot be implemented outside `crate::foo`
+  --> $DIR/impl-restriction-check.rs:46:1
+   |
+LL | impl foo::bar::FooBar for u8 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: trait restricted here
+  --> $DIR/impl-restriction-check.rs:21:20
+   |
+LL |         pub(crate) impl(in crate::foo) trait FooBar {}
+   |                    ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/impl-restriction/impl-restriction-check.rs b/tests/ui/impl-restriction/impl-restriction-check.rs
new file mode 100644
index 0000000..cf5e699
--- /dev/null
+++ b/tests/ui/impl-restriction/impl-restriction-check.rs
@@ -0,0 +1,49 @@
+//@ aux-build: external-impl-restriction.rs
+//@ revisions: e2015 e2018
+//@ [e2015] edition: 2015
+//@ [e2018] edition: 2018..
+#![feature(impl_restriction)]
+#![expect(incomplete_features)]
+
+extern crate external_impl_restriction as external;
+
+struct LocalType; // needed to avoid orphan rule errors
+
+impl external::TopLevel for LocalType {} //~ ERROR trait cannot be implemented outside `external`
+impl external::inner::Inner for LocalType {} //~ ERROR trait cannot be implemented outside `external`
+
+pub mod foo {
+    pub mod bar {
+        pub(crate) impl(self) trait Foo {}
+        pub(crate) impl(super) trait Bar {}
+        pub impl(crate) trait Baz {}
+        pub(crate) impl(in crate::foo::bar) trait Qux {}
+        pub(crate) impl(in crate::foo) trait FooBar {}
+
+        impl Foo for i16 {} // OK
+        impl Bar for i16 {} // OK
+        impl Baz for i16 {} // OK
+        impl Qux for i16 {} // OK
+        impl FooBar for i16 {} // OK
+    }
+
+    impl bar::Foo for i8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo::bar`
+    //[e2018]~^ ERROR trait cannot be implemented outside `crate::foo::bar`
+    impl bar::Bar for i8 {} // OK
+    impl bar::Baz for i8 {} // OK
+    impl bar::Qux for i8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo::bar`
+    //[e2018]~^ ERROR trait cannot be implemented outside `crate::foo::bar`
+    impl bar::FooBar for i8 {} // OK
+}
+
+impl foo::bar::Foo for u8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo::bar`
+//[e2018]~^ ERROR trait cannot be implemented outside `crate::foo::bar`
+impl foo::bar::Bar for u8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo`
+//[e2018]~^ ERROR trait cannot be implemented outside `crate::foo`
+impl foo::bar::Baz for u8 {} // OK
+impl foo::bar::Qux for u8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo::bar`
+//[e2018]~^ ERROR trait cannot be implemented outside `crate::foo::bar`
+impl foo::bar::FooBar for u8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo`
+//[e2018]~^ ERROR trait cannot be implemented outside `crate::foo`
+
+fn main() {}
diff --git a/tests/ui/impl-restriction/restriction_resolution_errors.rs b/tests/ui/impl-restriction/restriction_resolution_errors.rs
index b36f2cf..01173c1 100644
--- a/tests/ui/impl-restriction/restriction_resolution_errors.rs
+++ b/tests/ui/impl-restriction/restriction_resolution_errors.rs
@@ -1,6 +1,9 @@
+//@ aux-build: external-impl-restriction.rs
 #![feature(impl_restriction)]
 #![expect(incomplete_features)]
 
+extern crate external_impl_restriction as external;
+
 pub mod a {
     pub enum E {}
     pub mod d {}
@@ -53,6 +56,8 @@ pub mod h {}
 
 pub impl(super) trait T17 {} //~ ERROR too many leading `super` keywords [E0433]
 
+pub impl(in external) trait T18 {} //~ ERROR trait implementation can only be restricted to ancestor modules
+
 // Check if we can resolve paths referring to modules declared later.
 pub impl(in crate::j) trait L4 {} //~ ERROR trait implementation can only be restricted to ancestor modules
 
diff --git a/tests/ui/impl-restriction/restriction_resolution_errors.stderr b/tests/ui/impl-restriction/restriction_resolution_errors.stderr
index 5408032..48bfab2 100644
--- a/tests/ui/impl-restriction/restriction_resolution_errors.stderr
+++ b/tests/ui/impl-restriction/restriction_resolution_errors.stderr
@@ -1,71 +1,77 @@
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:14:21
+  --> $DIR/restriction_resolution_errors.rs:17:21
    |
 LL |         pub impl(in ::std) trait T2 {}
    |                     ^^^^^
 
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:16:21
+  --> $DIR/restriction_resolution_errors.rs:19:21
    |
 LL |         pub impl(in self::c) trait T3 {}
    |                     ^^^^^^^
 
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:18:21
+  --> $DIR/restriction_resolution_errors.rs:21:21
    |
 LL |         pub impl(in super::d) trait T4 {}
    |                     ^^^^^^^^
 
 error[E0433]: too many leading `super` keywords
-  --> $DIR/restriction_resolution_errors.rs:24:35
+  --> $DIR/restriction_resolution_errors.rs:27:35
    |
 LL |         pub impl(in super::super::super) trait T7 {}
    |                                   ^^^^^ there are too many leading `super` keywords
 
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:34:21
+  --> $DIR/restriction_resolution_errors.rs:37:21
    |
 LL |         pub impl(in self::f) trait L1 {}
    |                     ^^^^^^^
 
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:38:21
+  --> $DIR/restriction_resolution_errors.rs:41:21
    |
 LL |         pub impl(in super::h) trait L3 {}
    |                     ^^^^^^^^
 
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:47:13
+  --> $DIR/restriction_resolution_errors.rs:50:13
    |
 LL | pub impl(in crate::a) trait T13 {}
    |             ^^^^^^^^
 
 error[E0433]: too many leading `super` keywords
-  --> $DIR/restriction_resolution_errors.rs:54:10
+  --> $DIR/restriction_resolution_errors.rs:57:10
    |
 LL | pub impl(super) trait T17 {}
    |          ^^^^^ there are too many leading `super` keywords
 
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:57:13
+  --> $DIR/restriction_resolution_errors.rs:59:13
+   |
+LL | pub impl(in external) trait T18 {}
+   |             ^^^^^^^^
+
+error: trait implementation can only be restricted to ancestor modules
+  --> $DIR/restriction_resolution_errors.rs:62:13
    |
 LL | pub impl(in crate::j) trait L4 {}
    |             ^^^^^^^^
 
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:73:21
+  --> $DIR/restriction_resolution_errors.rs:78:21
    |
 LL |         pub impl(in crate::m2) trait U2 {}
    |                     ^^^^^^^^^
 
 error: trait implementation can only be restricted to ancestor modules
-  --> $DIR/restriction_resolution_errors.rs:75:21
+  --> $DIR/restriction_resolution_errors.rs:80:21
    |
 LL |         pub impl(in m6::m5) trait U4 {}
    |                     ^^^^^^
 
 error[E0433]: cannot find module or crate `a` in this scope
-  --> $DIR/restriction_resolution_errors.rs:12:21
+  --> $DIR/restriction_resolution_errors.rs:15:21
    |
 LL |         pub impl(in a::b) trait T1 {}
    |                     ^ use of unresolved module or unlinked crate `a`
@@ -81,25 +87,25 @@
    |
 
 error[E0433]: cannot find module `c` in the crate root
-  --> $DIR/restriction_resolution_errors.rs:20:28
+  --> $DIR/restriction_resolution_errors.rs:23:28
    |
 LL |         pub impl(in crate::c) trait T5 {}
    |                            ^ not found in the crate root
 
 error[E0577]: expected module, found enum `super::E`
-  --> $DIR/restriction_resolution_errors.rs:22:21
+  --> $DIR/restriction_resolution_errors.rs:25:21
    |
 LL |         pub impl(in super::E) trait T6 {}
    |                     ^^^^^^^^ not a module
 
 error[E0577]: expected module, found enum `super::G`
-  --> $DIR/restriction_resolution_errors.rs:36:21
+  --> $DIR/restriction_resolution_errors.rs:39:21
    |
 LL |         pub impl(in super::G) trait L2 {}
    |                     ^^^^^^^^ not a module
 
 error[E0577]: expected module, found enum `crate::a::E`
-  --> $DIR/restriction_resolution_errors.rs:49:13
+  --> $DIR/restriction_resolution_errors.rs:52:13
    |
 LL |     pub mod b {
    |     --------- similarly named module `b` defined here
@@ -114,7 +120,7 @@
    |
 
 error[E0577]: expected module, found enum `crate::I`
-  --> $DIR/restriction_resolution_errors.rs:59:13
+  --> $DIR/restriction_resolution_errors.rs:64:13
    |
 LL | pub mod a {
    | --------- similarly named module `a` defined here
@@ -129,12 +135,12 @@
    |
 
 error[E0577]: expected module, found enum `m7`
-  --> $DIR/restriction_resolution_errors.rs:76:21
+  --> $DIR/restriction_resolution_errors.rs:81:21
    |
 LL |         pub impl(in m7) trait U5 {}
    |                     ^^ not a module
 
-error: aborting due to 18 previous errors
+error: aborting due to 19 previous errors
 
 Some errors have detailed explanations: E0433, E0577.
 For more information about an error, try `rustc --explain E0433`.