From d5c756acf38aed410b885466559e9ba7d6850cf6 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sun, 22 Mar 2026 13:38:34 +0900 Subject: [PATCH 01/13] Lower `impl` restriction to HIR --- compiler/rustc_ast_lowering/src/item.rs | 37 +++++++++++++++++-- compiler/rustc_ast_lowering/src/path.rs | 17 +++++++++ compiler/rustc_hir/src/hir.rs | 27 ++++++++++++-- compiler/rustc_hir/src/intravisit.rs | 1 + .../src/collect/predicates_of.rs | 4 +- .../src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 16 ++++++++ .../rustc_hir_typeck/src/method/suggest.rs | 4 +- .../src/multiple_supertrait_upcastable.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 4 +- .../src/error_reporting/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 10 ++--- compiler/rustc_trait_selection/src/errors.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- .../src/arbitrary_source_item_ordering.rs | 2 +- .../clippy_lints/src/item_name_repetitions.rs | 2 +- .../clippy_lints/src/len_without_is_empty.rs | 2 +- .../clippy/clippy_lints/src/missing_doc.rs | 2 +- .../clippy/clippy_lints/src/trait_bounds.rs | 4 +- .../clippy_lints/src/upper_case_acronyms.rs | 2 +- 21 files changed, 115 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index fa103099e643f..4c8d34f1bd779 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -536,14 +536,14 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { 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, @@ -562,7 +562,16 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { (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); @@ -1827,6 +1836,28 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { } } + 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 { + path: self.lower_mod_path(did, path), + shorthand: *shorthand, + } + } 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_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 139140af3e033..cf0ef34a40515 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -250,6 +250,23 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { }) } + pub(crate) fn lower_mod_path(&mut self, res: DefId, p: &Path) -> &'hir hir::ModPath<'hir> { + self.arena.alloc(hir::ModPath { + res, + segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { + self.lower_path_segment( + p.span, + segment, + ParamMode::Explicit, + GenericArgsMode::Err, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ) + })), + span: self.lower_span(p.span), + }) + } + pub(crate) fn lower_path_segment( &mut self, path_span: Span, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 57cf42cc54794..d612bdacec7d4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -356,6 +356,9 @@ pub struct Path<'hir, R = Res> { /// Up to three resolutions for type, value and macro namespaces. pub type UsePath<'hir> = Path<'hir, PerNS>>; +/// Module paths. Used for restrictions. +pub type ModPath<'hir> = Path<'hir, DefId>; + impl Path<'_> { pub fn is_global(&self) -> bool { self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot) @@ -4326,13 +4329,14 @@ impl<'hir> Item<'hir> { 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); @@ -4401,6 +4405,20 @@ impl fmt::Display for Constness { } } +#[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 { path: &'hir ModPath<'hir>, shorthand: bool }, +} + /// 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 @@ -4513,6 +4531,7 @@ pub enum ItemKind<'hir> { Constness, IsAuto, Safety, + &'hir ImplRestriction<'hir>, Ident, &'hir Generics<'hir>, GenericBounds<'hir>, @@ -4563,7 +4582,7 @@ impl ItemKind<'_> { | 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) @@ -4581,7 +4600,7 @@ impl ItemKind<'_> { | 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 25ef56f8b0f2c..ae99ca7002248 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -622,6 +622,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: _constness, _is_auto, _safety, + _impl_restriction, ident, ref generics, bounds, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 8fd3d631962c8..33d5151236be0 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)); } @@ -1033,7 +1033,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 5bb4166bf6cb3..e5dae6ea2157c 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 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, '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_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 82540a9327410..07ee1118390eb 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -761,6 +761,7 @@ impl<'a> State<'a> { constness, is_auto, safety, + impl_restriction, ident, generics, bounds, @@ -770,6 +771,7 @@ impl<'a> State<'a> { 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,20 @@ impl<'a> State<'a> { hir::IsAuto::No => {} } } + + fn print_impl_restriction(&mut self, r: &hir::ImplRestriction<'_>) { + match r.kind { + hir::RestrictionKind::Unrestricted => {} + hir::RestrictionKind::Restricted { path, shorthand } => { + self.word("impl("); + if shorthand { + 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 c5b3d7065fa92..dc0a55649039d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1889,7 +1889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some( Node::Item(hir::Item { kind: - hir::ItemKind::Trait(_, _, _, ident, ..) + hir::ItemKind::Trait(_, _, _, _, ident, ..) | hir::ItemKind::TraitAlias(_, ident, ..), .. }) @@ -4533,7 +4533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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 93f067d09833a..9177e00d902c8 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -39,7 +39,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { 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 499c6dae060bf..20aa0a809006f 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -945,7 +945,7 @@ impl<'tcx> TyCtxt<'tcx> { }) => 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_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 6aeb0ae57e752..c201390fc5354 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -607,7 +607,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { 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) { @@ -1047,7 +1047,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { 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 bda0c4fa2c6f6..d4d8607fe9288 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -574,7 +574,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 2d9574ea8c546..e55f8274351cf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -271,7 +271,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { 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); @@ -334,7 +334,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } hir::Node::Item(hir::Item { kind: - hir::ItemKind::Trait(_, _, _, _, generics, ..) + hir::ItemKind::Trait(_, _, _, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }), .. }) if projection.is_some() => { @@ -358,7 +358,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { 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, _) @@ -438,7 +438,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { 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, _) @@ -3618,7 +3618,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { 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 34b9c9988f35c..32f1e894b3897 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -607,7 +607,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { 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 f54339429fa58..5ec1d352b7e20 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2875,7 +2875,7 @@ fn clean_maybe_renamed_item<'tcx>( 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) => { + ItemKind::Trait(_, _, _, _, _, 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 454026e80ab30..7f0f0a0245f4c 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 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { 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 70df856570b26..06bea4ba1ffd8 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 @@ impl LateLintPass<'_> for ItemNameRepetitions { | 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 1d219d7c3b74d..a3dc32dc77186 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 @@ declare_lint_pass!(LenWithoutIsEmpty => [LEN_WITHOUT_IS_EMPTY]); 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 89a61298bf19c..35e75d34a5d3a 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 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | 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 e7a785289f39f..4cd3707854c48 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 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // 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 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { .. }) = 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 6ea6a0ad85aa4..52dfcab363dbd 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 @@ impl LateLintPass<'_> for UpperCaseAcronyms { 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) => { From 01793db93cec6ad447ad558dd2a0dcb8495af727 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:13:42 +0900 Subject: [PATCH 02/13] Intravisit `hir::ImplRestriction` --- compiler/rustc_hir/src/intravisit.rs | 31 +++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ae99ca7002248..1de0547bdb107 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -433,6 +433,21 @@ pub trait Visitor<'v>: Sized { fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) -> Self::Result { walk_use(self, path, hir_id) } + fn visit_impl_restriction( + &mut self, + impl_restriction: &'v ImplRestriction<'v>, + ) -> Self::Result { + walk_impl_restriction(self, impl_restriction) + } + fn visit_restriction_kind( + &mut self, + restriction_kind: &'v RestrictionKind<'v>, + ) -> Self::Result { + match restriction_kind { + RestrictionKind::Unrestricted => Self::Result::output(), + RestrictionKind::Restricted { path, shorthand: _ } => walk_mod_path(self, path), + } + } fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) -> Self::Result { walk_trait_item(self, ti) } @@ -622,12 +637,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: _constness, _is_auto, _safety, - _impl_restriction, + ref impl_restriction, ident, ref generics, bounds, trait_item_refs, ) => { + try_visit!(visitor.visit_restriction_kind(&impl_restriction.kind)); try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); @@ -1260,6 +1276,19 @@ pub fn walk_use<'v, V: Visitor<'v>>( V::Result::output() } +pub fn walk_impl_restriction<'v, V: Visitor<'v>>( + visitor: &mut V, + impl_restriction: &'v ImplRestriction<'v>, +) -> V::Result { + visitor.visit_restriction_kind(&impl_restriction.kind) +} + +pub fn walk_mod_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v ModPath<'v>) -> V::Result { + let ModPath { segments, res: _, span: _ } = path; + walk_list!(visitor, visit_path_segment, *segments); + V::Result::output() +} + pub fn walk_trait_item<'v, V: Visitor<'v>>( visitor: &mut V, trait_item: &'v TraitItem<'v>, From bda0fcea83a9fadf28ca59b5a4e95bafbce46d0d Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:47:20 +0900 Subject: [PATCH 03/13] Lower `impl` restriction information to `TraitDef` --- compiler/rustc_hir_analysis/src/collect.rs | 25 ++++++++--- compiler/rustc_middle/src/ty/trait_def.rs | 49 ++++++++++++++++++++++ 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 80ef2001cc72e..426761f980293 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, shorthand: _ } = 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_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 3e69eda11ca63..d9c6bf9393fcf 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -24,6 +24,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 +100,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<'_>, krate: rustc_span::def_id::CrateNum) -> String { + match self { + ImplRestrictionKind::Unrestricted => String::new(), + ImplRestrictionKind::Restricted(restricted_to, _) => { + if restricted_to.krate == krate { + tcx.def_path_str(restricted_to) + } else { + tcx.crate_name(restricted_to.krate).to_ident_string() + } + } + } + } +} + #[derive(Default, Debug, HashStable)] pub struct TraitImpls { blanket_impls: Vec, From cdbccf7275e77fafd18edce5cb2422ea5d1d92e2 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:48:11 +0900 Subject: [PATCH 04/13] Emit error in implementation of restricted trait --- compiler/rustc_hir_analysis/src/coherence/mod.rs | 10 ++++++++++ compiler/rustc_hir_analysis/src/errors.rs | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 8f83761518bda..c60b40c61231f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -100,6 +100,16 @@ 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, rustc_hir::def_id::LOCAL_CRATE), + })); + } Ok(()) } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index fcd4cb938bf73..2e6a0e5ab6f67 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1027,6 +1027,16 @@ pub(crate) struct SpecializationTrait { pub span: Span, } +#[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 { From 222292a95121cb702d7678c1285fc6dfe7874c5b Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Fri, 27 Mar 2026 10:21:59 +0900 Subject: [PATCH 05/13] Add UI tests for semantic checks of `impl` restrictions --- .../auxiliary/external-impl-restriction.rs | 8 ++ .../impl-restriction-check.rs | 40 ++++++++ .../impl-restriction-check.stderr | 98 +++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 tests/ui/impl-restriction/auxiliary/external-impl-restriction.rs create mode 100644 tests/ui/impl-restriction/impl-restriction-check.rs create mode 100644 tests/ui/impl-restriction/impl-restriction-check.stderr 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 0000000000000..785aeedf56d55 --- /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.rs b/tests/ui/impl-restriction/impl-restriction-check.rs new file mode 100644 index 0000000000000..c41c818ac7af8 --- /dev/null +++ b/tests/ui/impl-restriction/impl-restriction-check.rs @@ -0,0 +1,40 @@ +//@ aux-build: external-impl-restriction.rs +#![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_restriction` +impl external::inner::Inner for LocalType {} //~ ERROR trait cannot be implemented outside `external_impl_restriction` + +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 {} //~ ERROR trait cannot be implemented outside `bar` + impl bar::Bar for i8 {} // OK + impl bar::Baz for i8 {} // OK + impl bar::Qux for i8 {} //~ ERROR trait cannot be implemented outside `bar` + impl bar::FooBar for i8 {} // OK +} + +impl foo::bar::Foo for u8 {} //~ ERROR trait cannot be implemented outside `bar` +impl foo::bar::Bar for u8 {} //~ ERROR trait cannot be implemented outside `foo` +impl foo::bar::Baz for u8 {} // OK +impl foo::bar::Qux for u8 {} //~ ERROR trait cannot be implemented outside `bar` +impl foo::bar::FooBar for u8 {} //~ ERROR trait cannot be implemented outside `foo` + +fn main() {} diff --git a/tests/ui/impl-restriction/impl-restriction-check.stderr b/tests/ui/impl-restriction/impl-restriction-check.stderr new file mode 100644 index 0000000000000..e8bc96fae3f96 --- /dev/null +++ b/tests/ui/impl-restriction/impl-restriction-check.stderr @@ -0,0 +1,98 @@ +error: trait cannot be implemented outside `external_impl_restriction` + --> $DIR/impl-restriction-check.rs:9: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_impl_restriction` + --> $DIR/impl-restriction-check.rs:10: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 `bar` + --> $DIR/impl-restriction-check.rs:27:5 + | +LL | impl bar::Foo for i8 {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: trait restricted here + --> $DIR/impl-restriction-check.rs:14:20 + | +LL | pub(crate) impl(self) trait Foo {} + | ^^^^^^^^^^ + +error: trait cannot be implemented outside `bar` + --> $DIR/impl-restriction-check.rs:34:1 + | +LL | impl foo::bar::Foo for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: trait restricted here + --> $DIR/impl-restriction-check.rs:14:20 + | +LL | pub(crate) impl(self) trait Foo {} + | ^^^^^^^^^^ + +error: trait cannot be implemented outside `foo` + --> $DIR/impl-restriction-check.rs:35:1 + | +LL | impl foo::bar::Bar for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: trait restricted here + --> $DIR/impl-restriction-check.rs:15:20 + | +LL | pub(crate) impl(super) trait Bar {} + | ^^^^^^^^^^^ + +error: trait cannot be implemented outside `bar` + --> $DIR/impl-restriction-check.rs:30:5 + | +LL | impl bar::Qux for i8 {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: trait restricted here + --> $DIR/impl-restriction-check.rs:17:20 + | +LL | pub(crate) impl(in crate::foo::bar) trait Qux {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait cannot be implemented outside `bar` + --> $DIR/impl-restriction-check.rs:37:1 + | +LL | impl foo::bar::Qux for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: trait restricted here + --> $DIR/impl-restriction-check.rs:17:20 + | +LL | pub(crate) impl(in crate::foo::bar) trait Qux {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait cannot be implemented outside `foo` + --> $DIR/impl-restriction-check.rs:38:1 + | +LL | impl foo::bar::FooBar for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: trait restricted here + --> $DIR/impl-restriction-check.rs:18:20 + | +LL | pub(crate) impl(in crate::foo) trait FooBar {} + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + From 159f1f24fa52fe9ca03ce30fc34e6b7ce62ca7b4 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:41:57 +0900 Subject: [PATCH 06/13] Call `visit_path_segment` directly --- compiler/rustc_hir/src/intravisit.rs | 32 +++------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1de0547bdb107..03b254cf7e352 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -433,21 +433,6 @@ pub trait Visitor<'v>: Sized { fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) -> Self::Result { walk_use(self, path, hir_id) } - fn visit_impl_restriction( - &mut self, - impl_restriction: &'v ImplRestriction<'v>, - ) -> Self::Result { - walk_impl_restriction(self, impl_restriction) - } - fn visit_restriction_kind( - &mut self, - restriction_kind: &'v RestrictionKind<'v>, - ) -> Self::Result { - match restriction_kind { - RestrictionKind::Unrestricted => Self::Result::output(), - RestrictionKind::Restricted { path, shorthand: _ } => walk_mod_path(self, path), - } - } fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) -> Self::Result { walk_trait_item(self, ti) } @@ -643,7 +628,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: bounds, trait_item_refs, ) => { - try_visit!(visitor.visit_restriction_kind(&impl_restriction.kind)); + if let RestrictionKind::Restricted { path, shorthand: _ } = &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); @@ -1276,19 +1263,6 @@ pub fn walk_use<'v, V: Visitor<'v>>( V::Result::output() } -pub fn walk_impl_restriction<'v, V: Visitor<'v>>( - visitor: &mut V, - impl_restriction: &'v ImplRestriction<'v>, -) -> V::Result { - visitor.visit_restriction_kind(&impl_restriction.kind) -} - -pub fn walk_mod_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v ModPath<'v>) -> V::Result { - let ModPath { segments, res: _, span: _ } = path; - walk_list!(visitor, visit_path_segment, *segments); - V::Result::output() -} - pub fn walk_trait_item<'v, V: Visitor<'v>>( visitor: &mut V, trait_item: &'v TraitItem<'v>, From 5863660b0d808f7336ebc09b70fff85b895448a0 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:53:30 +0900 Subject: [PATCH 07/13] Remove `shorthand` from HIR --- compiler/rustc_ast_lowering/src/item.rs | 7 ++----- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 6 ++---- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 4c8d34f1bd779..dae093683b7c1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1842,13 +1842,10 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { ) -> &'hir hir::ImplRestriction<'hir> { let kind = match &r.kind { RestrictionKind::Unrestricted => hir::RestrictionKind::Unrestricted, - RestrictionKind::Restricted { path, id, shorthand } => { + 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 { - path: self.lower_mod_path(did, path), - shorthand: *shorthand, - } + hir::RestrictionKind::Restricted(self.lower_mod_path(did, path)) } else { self.dcx().span_delayed_bug(path.span, "should have errored in resolve"); hir::RestrictionKind::Unrestricted diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d612bdacec7d4..9d686ea39d098 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4416,7 +4416,7 @@ pub enum RestrictionKind<'hir> { /// The restriction does not affect the item. Unrestricted, /// The restriction only applies outside of this path. - Restricted { path: &'hir ModPath<'hir>, shorthand: bool }, + Restricted(&'hir ModPath<'hir>), } /// The actual safety specified in syntax. We may treat diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 03b254cf7e352..99511189e9283 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -628,7 +628,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: bounds, trait_item_refs, ) => { - if let RestrictionKind::Restricted { path, shorthand: _ } = &impl_restriction.kind { + if let RestrictionKind::Restricted(path) = &impl_restriction.kind { walk_list!(visitor, visit_path_segment, path.segments); } try_visit!(visitor.visit_ident(ident)); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 426761f980293..14da2fff4609e 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -899,7 +899,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { false, is_auto == hir::IsAuto::Yes, safety, - if let hir::RestrictionKind::Restricted { path, shorthand: _ } = impl_restriction.kind { + 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 diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 07ee1118390eb..6f64d07b01d66 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2651,11 +2651,9 @@ impl<'a> State<'a> { fn print_impl_restriction(&mut self, r: &hir::ImplRestriction<'_>) { match r.kind { hir::RestrictionKind::Unrestricted => {} - hir::RestrictionKind::Restricted { path, shorthand } => { + hir::RestrictionKind::Restricted(path) => { self.word("impl("); - if shorthand { - self.word_nbsp("in"); - } + self.word_nbsp("in"); self.print_path(path, false); self.word(")"); } From 4f1260910a5fb54e3eb3e5ba8f4587c01c685479 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sat, 4 Apr 2026 17:16:14 +0900 Subject: [PATCH 08/13] Remove the type alias for `Path<'hir, DefId>` --- compiler/rustc_ast_lowering/src/item.rs | 19 ++++++++++++++++--- compiler/rustc_ast_lowering/src/path.rs | 17 ----------------- compiler/rustc_hir/src/hir.rs | 5 +---- 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dae093683b7c1..a721f41a6afef 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -24,8 +24,8 @@ use tracing::instrument; 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 @@ -1845,7 +1845,20 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { 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.lower_mod_path(did, path)) + 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 diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index cf0ef34a40515..139140af3e033 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -250,23 +250,6 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { }) } - pub(crate) fn lower_mod_path(&mut self, res: DefId, p: &Path) -> &'hir hir::ModPath<'hir> { - self.arena.alloc(hir::ModPath { - res, - segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { - self.lower_path_segment( - p.span, - segment, - ParamMode::Explicit, - GenericArgsMode::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), - None, - ) - })), - span: self.lower_span(p.span), - }) - } - pub(crate) fn lower_path_segment( &mut self, path_span: Span, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 9d686ea39d098..e4e6642981d1a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -356,9 +356,6 @@ pub struct Path<'hir, R = Res> { /// Up to three resolutions for type, value and macro namespaces. pub type UsePath<'hir> = Path<'hir, PerNS>>; -/// Module paths. Used for restrictions. -pub type ModPath<'hir> = Path<'hir, DefId>; - impl Path<'_> { pub fn is_global(&self) -> bool { self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot) @@ -4416,7 +4413,7 @@ pub enum RestrictionKind<'hir> { /// The restriction does not affect the item. Unrestricted, /// The restriction only applies outside of this path. - Restricted(&'hir ModPath<'hir>), + Restricted(&'hir Path<'hir, DefId>), } /// The actual safety specified in syntax. We may treat From 65effbf5d6ab29b21b209856381b78ec98e8a0f6 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sat, 4 Apr 2026 21:42:52 +0900 Subject: [PATCH 09/13] Add a FIXME for rustdoc handling `impl` restrictions --- src/librustdoc/clean/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5ec1d352b7e20..a7133c6993e0e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2875,7 +2875,8 @@ fn clean_maybe_renamed_item<'tcx>( 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)) From 2f400deab37048251c78bca2e9201aef6978d9fb Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sun, 5 Apr 2026 13:15:21 +0900 Subject: [PATCH 10/13] Modify `restriction_path` --- compiler/rustc_middle/src/ty/trait_def.rs | 5 +- ...rr => impl-restriction-check.e2015.stderr} | 40 ++++---- .../impl-restriction-check.e2018.stderr | 98 +++++++++++++++++++ .../impl-restriction-check.rs | 25 +++-- 4 files changed, 138 insertions(+), 30 deletions(-) rename tests/ui/impl-restriction/{impl-restriction-check.stderr => impl-restriction-check.e2015.stderr} (72%) create mode 100644 tests/ui/impl-restriction/impl-restriction-check.e2018.stderr diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index d9c6bf9393fcf..70eba8308da47 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -12,6 +12,7 @@ use tracing::debug; 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. @@ -137,9 +138,9 @@ impl ImplRestrictionKind { ImplRestrictionKind::Unrestricted => String::new(), ImplRestrictionKind::Restricted(restricted_to, _) => { if restricted_to.krate == krate { - tcx.def_path_str(restricted_to) + with_crate_prefix!(with_no_trimmed_paths!(tcx.def_path_str(restricted_to))) } else { - tcx.crate_name(restricted_to.krate).to_ident_string() + with_no_trimmed_paths!(tcx.def_path_str(restricted_to)) } } } diff --git a/tests/ui/impl-restriction/impl-restriction-check.stderr b/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr similarity index 72% rename from tests/ui/impl-restriction/impl-restriction-check.stderr rename to tests/ui/impl-restriction/impl-restriction-check.e2015.stderr index e8bc96fae3f96..0534705835f4c 100644 --- a/tests/ui/impl-restriction/impl-restriction-check.stderr +++ b/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr @@ -1,5 +1,5 @@ -error: trait cannot be implemented outside `external_impl_restriction` - --> $DIR/impl-restriction-check.rs:9:1 +error: trait cannot be implemented outside `external` + --> $DIR/impl-restriction-check.rs:12:1 | LL | impl external::TopLevel for LocalType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,8 +10,8 @@ note: trait restricted here LL | pub impl(crate) trait TopLevel {} | ^^^^^^^^^^^ -error: trait cannot be implemented outside `external_impl_restriction` - --> $DIR/impl-restriction-check.rs:10:1 +error: trait cannot be implemented outside `external::inner` + --> $DIR/impl-restriction-check.rs:13:1 | LL | impl external::inner::Inner for LocalType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,74 +22,74 @@ note: trait restricted here LL | pub impl(self) trait Inner {} | ^^^^^^^^^^ -error: trait cannot be implemented outside `bar` - --> $DIR/impl-restriction-check.rs:27:5 +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:14:20 + --> $DIR/impl-restriction-check.rs:17:20 | LL | pub(crate) impl(self) trait Foo {} | ^^^^^^^^^^ -error: trait cannot be implemented outside `bar` - --> $DIR/impl-restriction-check.rs:34:1 +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:14:20 + --> $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:35:1 + --> $DIR/impl-restriction-check.rs:41:1 | LL | impl foo::bar::Bar for u8 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: trait restricted here - --> $DIR/impl-restriction-check.rs:15:20 + --> $DIR/impl-restriction-check.rs:18:20 | LL | pub(crate) impl(super) trait Bar {} | ^^^^^^^^^^^ -error: trait cannot be implemented outside `bar` - --> $DIR/impl-restriction-check.rs:30:5 +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:17:20 + --> $DIR/impl-restriction-check.rs:20:20 | LL | pub(crate) impl(in crate::foo::bar) trait Qux {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: trait cannot be implemented outside `bar` - --> $DIR/impl-restriction-check.rs:37:1 +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:17:20 + --> $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:38:1 + --> $DIR/impl-restriction-check.rs:46:1 | LL | impl foo::bar::FooBar for u8 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: trait restricted here - --> $DIR/impl-restriction-check.rs:18:20 + --> $DIR/impl-restriction-check.rs:21:20 | LL | pub(crate) impl(in crate::foo) trait FooBar {} | ^^^^^^^^^^^^^^^^^^^ 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 0000000000000..d350c7f514142 --- /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::inner` + --> $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 index c41c818ac7af8..b4dd64de0c054 100644 --- a/tests/ui/impl-restriction/impl-restriction-check.rs +++ b/tests/ui/impl-restriction/impl-restriction-check.rs @@ -1,4 +1,7 @@ //@ aux-build: external-impl-restriction.rs +//@ revisions: e2015 e2018 +//@ [e2015] edition: 2015 +//@ [e2018] edition: 2018.. #![feature(impl_restriction)] #![expect(incomplete_features)] @@ -6,8 +9,8 @@ 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_restriction` -impl external::inner::Inner for LocalType {} //~ ERROR trait cannot be implemented outside `external_impl_restriction` +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::inner` pub mod foo { pub mod bar { @@ -24,17 +27,23 @@ pub mod foo { impl FooBar for i16 {} // OK } - impl bar::Foo for i8 {} //~ ERROR trait cannot be implemented outside `bar` + 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 {} //~ ERROR trait cannot be implemented outside `bar` + 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 {} //~ ERROR trait cannot be implemented outside `bar` -impl foo::bar::Bar for u8 {} //~ ERROR trait cannot be implemented outside `foo` +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 {} //~ ERROR trait cannot be implemented outside `bar` -impl foo::bar::FooBar for u8 {} //~ ERROR trait cannot be implemented outside `foo` +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() {} From 6f9727342f6e4c3ebe6b2934999e2ee6b646c404 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sun, 5 Apr 2026 13:18:00 +0900 Subject: [PATCH 11/13] Add non-ancestor errors involving restrictions to other crates --- .../restriction_resolution_errors.rs | 5 +++ .../restriction_resolution_errors.stderr | 44 +++++++++++-------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/tests/ui/impl-restriction/restriction_resolution_errors.rs b/tests/ui/impl-restriction/restriction_resolution_errors.rs index b36f2cf9bdfba..01173c111ae76 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 impl(self) trait T16 {} 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 540803285c1b5..48bfab2bc1eb7 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 @@ LL + use a; | 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 @@ LL + pub impl(in crate::a::b) trait T14 {} | 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 @@ LL + pub impl(in crate::a) trait L5 {} | 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`. From 72c1d65037573c0a9004ff036898a8a56577735b Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Sun, 5 Apr 2026 20:54:36 +0900 Subject: [PATCH 12/13] Inline `krate` --- compiler/rustc_hir_analysis/src/coherence/mod.rs | 4 +--- compiler/rustc_middle/src/ty/trait_def.rs | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index c60b40c61231f..261be884025f1 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -105,9 +105,7 @@ fn enforce_trait_manually_implementable( 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, rustc_hir::def_id::LOCAL_CRATE), + restriction_path: trait_def.impl_restriction.restriction_path(tcx), })); } Ok(()) diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 70eba8308da47..a58a9c9d75792 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -133,11 +133,11 @@ impl ImplRestrictionKind { } /// Obtain the path of the restriction. If unrestricted, an empty string is returned. - pub fn restriction_path(self, tcx: TyCtxt<'_>, krate: rustc_span::def_id::CrateNum) -> String { + pub fn restriction_path(self, tcx: TyCtxt<'_>) -> String { match self { ImplRestrictionKind::Unrestricted => String::new(), ImplRestrictionKind::Restricted(restricted_to, _) => { - if restricted_to.krate == krate { + if restricted_to.krate == rustc_hir::def_id::LOCAL_CRATE { with_crate_prefix!(with_no_trimmed_paths!(tcx.def_path_str(restricted_to))) } else { with_no_trimmed_paths!(tcx.def_path_str(restricted_to)) From 46befd885d24b2f019c880093de5e098d2e1bd44 Mon Sep 17 00:00:00 2001 From: CoCo-Japan-pan <115922543+CoCo-Japan-pan@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:40:29 +0900 Subject: [PATCH 13/13] Display only crate name for external trait `impl` restrictions --- compiler/rustc_middle/src/ty/trait_def.rs | 2 +- tests/ui/impl-restriction/impl-restriction-check.e2015.stderr | 2 +- tests/ui/impl-restriction/impl-restriction-check.e2018.stderr | 2 +- tests/ui/impl-restriction/impl-restriction-check.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index a58a9c9d75792..af5d81a108ba7 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -140,7 +140,7 @@ impl ImplRestrictionKind { if restricted_to.krate == rustc_hir::def_id::LOCAL_CRATE { with_crate_prefix!(with_no_trimmed_paths!(tcx.def_path_str(restricted_to))) } else { - with_no_trimmed_paths!(tcx.def_path_str(restricted_to)) + tcx.def_path_str(restricted_to.krate.as_mod_def_id()) } } } diff --git a/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr b/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr index 0534705835f4c..402464f8a545d 100644 --- a/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr +++ b/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr @@ -10,7 +10,7 @@ note: trait restricted here LL | pub impl(crate) trait TopLevel {} | ^^^^^^^^^^^ -error: trait cannot be implemented outside `external::inner` +error: trait cannot be implemented outside `external` --> $DIR/impl-restriction-check.rs:13:1 | LL | impl external::inner::Inner for LocalType {} diff --git a/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr b/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr index d350c7f514142..8bd256cc9cae6 100644 --- a/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr +++ b/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr @@ -10,7 +10,7 @@ note: trait restricted here LL | pub impl(crate) trait TopLevel {} | ^^^^^^^^^^^ -error: trait cannot be implemented outside `external::inner` +error: trait cannot be implemented outside `external` --> $DIR/impl-restriction-check.rs:13:1 | LL | impl external::inner::Inner for LocalType {} diff --git a/tests/ui/impl-restriction/impl-restriction-check.rs b/tests/ui/impl-restriction/impl-restriction-check.rs index b4dd64de0c054..cf5e699dfce91 100644 --- a/tests/ui/impl-restriction/impl-restriction-check.rs +++ b/tests/ui/impl-restriction/impl-restriction-check.rs @@ -10,7 +10,7 @@ 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::inner` +impl external::inner::Inner for LocalType {} //~ ERROR trait cannot be implemented outside `external` pub mod foo { pub mod bar {