From 6074adc3a4ac75aaec3bc764f0e054c75efab47a Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 09:01:30 -0500 Subject: [PATCH 1/3] Add mod_id to FnCtxt --- compiler/rustc_hir_typeck/src/expr.rs | 39 +++++++------------ .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 9 +---- .../rustc_hir_typeck/src/method/suggest.rs | 13 +------ compiler/rustc_hir_typeck/src/pat.rs | 4 +- .../rustc_hir_typeck/src/typeck_root_ctxt.rs | 7 +++- 6 files changed, 26 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 3bcad2460e78f..4ef0bba9b3024 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2215,9 +2215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let private_fields: Vec<&ty::FieldDef> = variant .fields .iter() - .filter(|field| { - !field.vis.is_accessible_from(tcx.parent_module(expr.hir_id), tcx) - }) + .filter(|field| !field.vis.is_accessible_from(self.mod_id, tcx)) .collect(); if !private_fields.is_empty() { @@ -2689,7 +2687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .filter(|field| { skip_fields.iter().all(|&skip| skip.ident.name != field.name) - && self.is_field_suggestable(field, expr.hir_id, expr.span) + && self.is_field_suggestable(field, expr.span) }) .map(|field| field.name) .collect() @@ -3244,7 +3242,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // try to add a suggestion in case the field is a nested field of a field of the Adt - let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id(); let (ty, unwrap) = if let ty::Adt(def, args) = base_ty.kind() && (self.tcx.is_diagnostic_item(sym::Result, def.did()) || self.tcx.is_diagnostic_item(sym::Option, def.did())) @@ -3255,9 +3252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (base_ty, "") }; - for found_fields in - self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, expr.hir_id) - { + for found_fields in self.get_field_candidates_considering_privacy_for_diag(span, ty) { let field_names = found_fields.iter().map(|field| field.0.name).collect::>(); let mut candidate_fields: Vec<_> = found_fields .into_iter() @@ -3267,8 +3262,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &|candidate_field, _| candidate_field == field, candidate_field, vec![], - mod_id, - expr.hir_id, ) }) .map(|mut field_path| { @@ -3329,8 +3322,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, span: Span, base_ty: Ty<'tcx>, - mod_id: DefId, - hir_id: HirId, ) -> Vec)>> { debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty); @@ -3354,15 +3345,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Some struct, e.g. some that impl `Deref`, have all private fields // because you're expected to deref them to access the _real_ fields. // This, for example, will help us suggest accessing a field through a `Box`. - if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { + if fields + .iter() + .all(|field| !field.vis.is_accessible_from(self.mod_id, tcx)) + { return None; } return Some( fields .iter() .filter(move |field| { - field.vis.is_accessible_from(mod_id, tcx) - && self.is_field_suggestable(field, hir_id, span) + field.vis.is_accessible_from(self.mod_id, tcx) + && self.is_field_suggestable(field, span) }) // For compile-time reasons put a limit on number of fields we search .take(100) @@ -3394,15 +3388,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// This method is called after we have encountered a missing field error to recursively /// search for the field - #[instrument(skip(self, matches, mod_id, hir_id), level = "debug")] + #[instrument(skip(self, matches), level = "debug")] pub(crate) fn check_for_nested_field_satisfying_condition_for_diag( &self, span: Span, matches: &impl Fn(Ident, Ty<'tcx>) -> bool, (candidate_name, candidate_ty): (Ident, Ty<'tcx>), mut field_path: Vec, - mod_id: DefId, - hir_id: HirId, ) -> Option> { if field_path.len() > 3 { // For compile-time reasons and to avoid infinite recursion we only check for fields @@ -3413,12 +3405,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if matches(candidate_name, candidate_ty) { return Some(field_path); } - for nested_fields in self.get_field_candidates_considering_privacy_for_diag( - span, - candidate_ty, - mod_id, - hir_id, - ) { + for nested_fields in + self.get_field_candidates_considering_privacy_for_diag(span, candidate_ty) + { // recursively search fields of `candidate_field` if it's a ty::Adt for field in nested_fields { if let Some(field_path) = self.check_for_nested_field_satisfying_condition_for_diag( @@ -3426,8 +3415,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { matches, field, field_path.clone(), - mod_id, - hir_id, ) { return Some(field_path); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9a1b1f8300957..f3ec17d4833a0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1237,7 +1237,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap(); // Check the visibility of the ctor. let vis = tcx.visibility(ctor_def_id); - if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) { + if !vis.is_accessible_from(self.mod_id, tcx) { self.dcx() .emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) }); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b28eb8ad940d9..1ae3e4b732d3b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2280,14 +2280,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(crate) fn is_field_suggestable( - &self, - field: &ty::FieldDef, - hir_id: HirId, - span: Span, - ) -> bool { + pub(crate) fn is_field_suggestable(&self, field: &ty::FieldDef, span: Span) -> bool { // The field must be visible in the containing module. - field.vis.is_accessible_from(self.tcx.parent_module(hir_id), self.tcx) + field.vis.is_accessible_from(self.mod_id, self.tcx) // The field must not be unstable. && !matches!( self.tcx.eval_stability(field.did, None, rustc_span::DUMMY_SP, None), diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4365a95b4bd81..ad11187cf8511 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2844,8 +2844,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }); if let Some((field, field_ty)) = field_receiver { - let scope = tcx.parent_module_from_def_id(self.body_def_id); - let is_accessible = field.vis.is_accessible_from(scope, tcx); + let is_accessible = field.vis.is_accessible_from(self.mod_id, tcx); if is_accessible { if let Some((what, _, _)) = self.extract_callable_info(field_ty) { @@ -3207,13 +3206,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_type: Option>, ) { if let SelfSource::MethodCall(expr) = source { - let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id(); - for fields in self.get_field_candidates_considering_privacy_for_diag( - span, - actual, - mod_id, - expr.hir_id, - ) { + for fields in self.get_field_candidates_considering_privacy_for_diag(span, actual) { let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(expr.hir_id)); let lang_items = self.tcx.lang_items(); @@ -3248,8 +3241,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, candidate_field, vec![], - mod_id, - expr.hir_id, ) }) .map(|field_path| { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 52602b8041d66..3db2531f6ef47 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2172,7 +2172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let accessible_unmentioned_fields: Vec<_> = unmentioned_fields .iter() .copied() - .filter(|(field, _)| self.is_field_suggestable(field, pat.hir_id, pat.span)) + .filter(|(field, _)| self.is_field_suggestable(field, pat.span)) .collect(); if !has_rest_pat { @@ -2345,7 +2345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if let [(field_def, field)] = unmentioned_fields.as_slice() - && self.is_field_suggestable(field_def, pat.hir_id, pat.span) + && self.is_field_suggestable(field_def, pat.span) { let suggested_name = find_best_match_for_name(&[field.name], pat_field.ident.name, None); diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index e4dcead1f7954..55339ded49714 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -7,7 +7,7 @@ use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInf use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt, TyVid, TypeVisitableExt, TypingMode}; use rustc_span::Span; -use rustc_span::def_id::LocalDefIdMap; +use rustc_span::def_id::{LocalDefIdMap, LocalModId}; use rustc_trait_selection::traits::{self, FulfillmentError, TraitEngine, TraitEngineExt as _}; use tracing::instrument; @@ -66,6 +66,9 @@ pub(crate) struct TypeckRootCtxt<'tcx> { /// we record that type variable here. This is later used to inform /// fallback. See the `fallback` module for details. pub(super) diverging_type_vars: RefCell>, + + /// Parent module + pub(super) mod_id: LocalModId, } impl<'tcx> Deref for TypeckRootCtxt<'tcx> { @@ -77,6 +80,7 @@ impl<'tcx> Deref for TypeckRootCtxt<'tcx> { impl<'tcx> TypeckRootCtxt<'tcx> { pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + let mod_id = tcx.parent_module_from_def_id(def_id); let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; let infcx = tcx @@ -100,6 +104,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> { deferred_asm_checks: RefCell::new(Vec::new()), deferred_repeat_expr_checks: RefCell::new(Vec::new()), diverging_type_vars: RefCell::new(Default::default()), + mod_id, } } From 508bb161c23f0a2f72e7d60d9ab05ac1eae9ecf6 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 11:30:20 -0500 Subject: [PATCH 2/3] Restrict Visibility methods to ModId We generally expect Visibility to have ModId or LocalModId, so it seems good to restrict the impls as such. There is just one error path needing adjustment to check that we actually have a ModId. It should be okay since, if it is not a module, an error will be emitted elsewhere. --- compiler/rustc_middle/src/ty/mod.rs | 16 ++++++++-------- compiler/rustc_resolve/src/late.rs | 27 +++++++++++++-------------- compiler/rustc_resolve/src/lib.rs | 2 +- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9b582eeb2c520..75d4125f47e92 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -447,19 +447,19 @@ impl Visibility { } } -impl> Visibility { - /// Returns `true` if an item with this visibility is accessible from the given module. - pub fn is_accessible_from(self, module: impl Into, tcx: TyCtxt<'_>) -> bool { +impl> Visibility { + /// Returns `true` if an item with this visibility is accessible from the given definition. + pub fn is_accessible_from(self, def_id: impl Into, tcx: TyCtxt<'_>) -> bool { match self { // Public items are visible everywhere. Visibility::Public => true, - Visibility::Restricted(id) => tcx.is_descendant_of(module, id), + Visibility::Restricted(id) => tcx.is_descendant_of(def_id, id.into()), } } pub fn partial_cmp( self, - vis: Visibility>, + vis: Visibility>, tcx: TyCtxt<'_>, ) -> Option { match (self, vis) { @@ -468,18 +468,18 @@ impl> Visibility { (Visibility::Restricted(_), Visibility::Public) => Some(Ordering::Less), (Visibility::Restricted(lhs_id), Visibility::Restricted(rhs_id)) => { let (lhs_id, rhs_id) = (lhs_id.into(), rhs_id.into()); - tcx.def_id_partial_cmp(lhs_id, rhs_id) + tcx.def_id_partial_cmp(lhs_id.to_def_id(), rhs_id.to_def_id()) } } } } -impl + Debug + Copy> Visibility { +impl + Debug + Copy> Visibility { /// Returns `true` if this visibility is strictly larger than the given visibility. #[track_caller] pub fn greater_than( self, - vis: Visibility + Debug + Copy>, + vis: Visibility + Debug + Copy>, tcx: TyCtxt<'_>, ) -> bool { match self.partial_cmp(vis, tcx) { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2726598c40894..7e3c430642e7b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -34,6 +34,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; use rustc_session::diagnostics::feature_err; use rustc_session::lint; +use rustc_span::def_id::ModId; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Spanned, Symbol, kw, respan, sym}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; @@ -4515,21 +4516,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ast::RestrictionKind::Unrestricted => (), ast::RestrictionKind::Restricted { path, id, shorthand: _ } => { self.smart_resolve_path(*id, &None, path, PathSource::Module); - if let Some(res) = self.r.partial_res_map[&id].full_res() - && let Some(def_id) = res.opt_def_id() - { - if !self.r.is_accessible_from( - Visibility::Restricted(def_id), + if let Some(Res::Def(DefKind::Mod, mod_id)) = self.r.partial_res_map[&id].full_res() + && !self.r.is_accessible_from( + Visibility::Restricted(ModId::new_unchecked(mod_id)), self.parent_scope.module, - ) { - self.r - .dcx() - .create_err(crate::diagnostics::RestrictionAncestorOnly { - span: path.span, - kind, - }) - .emit(); - } + ) + { + self.r + .dcx() + .create_err(crate::diagnostics::RestrictionAncestorOnly { + span: path.span, + kind, + }) + .emit(); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 111eae6a4134f..d3e5a073fafb6 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2371,7 +2371,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.pat_span_map.insert(node, span); } - fn is_accessible_from(&self, vis: Visibility>, module: Module<'ra>) -> bool { + fn is_accessible_from(&self, vis: Visibility>, module: Module<'ra>) -> bool { vis.is_accessible_from(module.nearest_parent_mod(), self.tcx) } From 59f64b4ad79ebc0b5eb266ff4b13d71b1d419a59 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 11:37:23 -0500 Subject: [PATCH 3/3] Cache and use LocalModId more --- compiler/rustc_hir_analysis/src/collect.rs | 8 ++++ .../src/hir_ty_lowering/errors.rs | 5 +-- .../src/hir_ty_lowering/mod.rs | 16 ++++---- compiler/rustc_hir_typeck/src/expr.rs | 16 +++----- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 5 +++ compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- .../rustc_hir_typeck/src/method/suggest.rs | 5 +-- compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_privacy/src/lib.rs | 40 +++++-------------- .../src/error_reporting/traits/suggestions.rs | 2 +- 10 files changed, 46 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b520ea106dfa0..d061af5da2097 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -36,6 +36,7 @@ use rustc_middle::ty::{ Unnormalized, fold_regions, }; use rustc_middle::{bug, span_bug}; +use rustc_span::def_id::LocalModId; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; use rustc_trait_selection::infer::InferCtxtExt; @@ -128,6 +129,7 @@ pub(crate) fn provide(providers: &mut Providers) { pub(crate) struct ItemCtxt<'tcx> { tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, + mod_id: LocalModId, tainted_by_errors: Cell>, lowering_delegation_segment: bool, } @@ -248,9 +250,11 @@ impl<'tcx> ItemCtxt<'tcx> { item_def_id: LocalDefId, delegation: bool, ) -> ItemCtxt<'tcx> { + let mod_id = tcx.parent_module_from_def_id(item_def_id); ItemCtxt { tcx, item_def_id, + mod_id, tainted_by_errors: Cell::new(None), lowering_delegation_segment: delegation, } @@ -331,6 +335,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { self.item_def_id } + fn mod_id(&self) -> LocalModId { + self.mod_id + } + fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { if let RegionInferReason::ObjectLifetimeDefault(sugg_sp) = reason { // FIXME: Account for trailing plus `dyn Trait+`, the need of parens in diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 460ef9d56dee5..452f14229e3e4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -199,8 +199,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .visible_traits() .filter(|trait_def_id| { let viz = tcx.visibility(*trait_def_id); - let def_id = self.item_def_id(); - viz.is_accessible_from(def_id, tcx) + viz.is_accessible_from(self.mod_id(), tcx) }) .collect(); @@ -569,7 +568,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) .filter(|header| { // Consider only accessible traits - tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) + tcx.visibility(trait_def_id).is_accessible_from(self.mod_id(), tcx) && header.polarity != ty::ImplPolarity::Negative }) .map(|header| header.trait_ref.instantiate_identity().skip_norm_wip().self_ty()) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index b59bed76eadd7..f27199fe77737 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -45,7 +45,7 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; -use rustc_span::def_id::ModId; +use rustc_span::def_id::{LocalModId, ModId}; use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, FulfillmentError}; @@ -137,6 +137,9 @@ pub trait HirTyLowerer<'tcx> { /// Returns the [`LocalDefId`] of the overarching item whose constituents get lowered. fn item_def_id(&self) -> LocalDefId; + /// Returns the containing module. + fn mod_id(&self) -> LocalModId; + /// Returns the region to use when a lifetime is omitted (and not elided). fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx>; @@ -1810,7 +1813,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Option<(ty::AssocItem, /*scope*/ ModId)> { let tcx = self.tcx(); - let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, self.item_def_id()); + let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, self.mod_id()); // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` // instead of calling `filter_by_name_and_kind` which would needlessly normalize the // `ident` again and again. @@ -1875,7 +1878,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) // Consider only accessible traits && tcx.visibility(*trait_def_id) - .is_accessible_from(self.item_def_id(), tcx) + .is_accessible_from(self.mod_id(), tcx) && tcx.all_impls(*trait_def_id) .any(|impl_def_id| { let header = tcx.impl_trait_header(impl_def_id); @@ -3412,7 +3415,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } hir::TyKind::FieldOf(ty, hir::TyFieldPath { variant, field }) => self.lower_field_of( self.lower_ty(ty), - self.item_def_id(), + self.mod_id(), ty.span, hir_ty.hir_id, *variant, @@ -3466,7 +3469,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn lower_field_of( &self, ty: Ty<'tcx>, - item_def_id: LocalDefId, + mod_id: LocalModId, ty_span: Span, hir_id: HirId, variant: Option, @@ -3516,8 +3519,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } (FIRST_VARIANT, def.non_enum_variant()) }; - let (ident, def_scope) = - tcx.adjust_ident_and_get_scope(field, def.did(), item_def_id); + let (ident, def_scope) = tcx.adjust_ident_and_get_scope(field, def.did(), mod_id); if let Some((field_idx, field)) = variant .fields .iter_enumerated() diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4ef0bba9b3024..96c2228c2117e 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2763,11 +2763,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ty::new_error(self.tcx(), guar); } - let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope( - field, - base_def.did(), - self.body_def_id, - ); + let (ident, def_scope) = + self.tcx.adjust_ident_and_get_scope(field, base_def.did(), self.mod_id); if let Some((idx, field)) = self.find_adt_field(*base_def, ident) { self.write_field_index(expr.hir_id, idx); @@ -3793,11 +3790,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); break; }; - let (subident, sub_def_scope) = self.tcx.adjust_ident_and_get_scope( - subfield, - variant.def_id, - self.body_def_id, - ); + let (subident, sub_def_scope) = + self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, self.mod_id); let Some((subindex, field)) = variant .fields @@ -3848,7 +3842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope( field, container_def.did(), - self.body_def_id, + self.mod_id, ); let fields = &container_def.non_enum_variant().fields; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index b255951baefa6..de50fa12a4b55 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -22,6 +22,7 @@ use rustc_middle::ty::{ self, CantBeErased, Const, Flags, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, }; use rustc_session::Session; +use rustc_span::def_id::LocalModId; use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span}; use rustc_trait_selection::error_reporting::TypeErrCtxt; use rustc_trait_selection::traits::{ @@ -233,6 +234,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { self.body_def_id } + fn mod_id(&self) -> LocalModId { + self.mod_id + } + fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { let v = match reason { RegionInferReason::Param(def) => { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index dfb4647b5e6e2..c64f8deb10ba0 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -848,8 +848,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let is_accessible = if let Some(name) = self.method_name { let item = candidate.item; let container_id = item.container_id(self.tcx); - let def_scope = - self.tcx.adjust_ident_and_get_scope(name, container_id, self.body_def_id).1; + let def_scope = self.tcx.adjust_ident_and_get_scope(name, container_id, self.mod_id).1; item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx) } else { true diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index ad11187cf8511..ecc3ad5729c1d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3990,11 +3990,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let parent_map = self.tcx.visible_parent_map(()); - let scope = self.tcx.parent_module_from_def_id(self.body_def_id); let (accessible_candidates, inaccessible_candidates): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|id| { let vis = self.tcx.visibility(*id); - vis.is_accessible_from(scope, self.tcx) + vis.is_accessible_from(self.mod_id, self.tcx) }); let sugg = |candidates: Vec<_>, visible| { @@ -4048,7 +4047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let accessible_sugg = sugg(accessible_candidates, true); let inaccessible_sugg = sugg(inaccessible_candidates, false); - let (module, _, _) = self.tcx.hir_get_module(scope); + let (module, _, _) = self.tcx.hir_get_module(self.mod_id); let span = module.spans.inject_use_span; handle_candidates(accessible_sugg, inaccessible_sugg, span); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 75d4125f47e92..06afa3461b1f0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2178,13 +2178,13 @@ impl<'tcx> TyCtxt<'tcx> { self, mut ident: Ident, scope: DefId, - item_id: LocalDefId, + mod_id: LocalModId, ) -> (Ident, ModId) { let scope = ident .span .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) .and_then(|actual_expansion| actual_expansion.expn_data().parent_module) - .unwrap_or_else(|| self.parent_module_from_def_id(item_id).to_mod_id()); + .unwrap_or(mod_id.to_mod_id()); (ident, scope) } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 29ee27bc102f9..7db09c2d60bf1 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -917,6 +917,7 @@ impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> { /// This pass performs remaining checks for fields in struct expressions and patterns. struct NamePrivacyVisitor<'tcx> { tcx: TyCtxt<'tcx>, + mod_id: LocalModId, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, } @@ -933,7 +934,6 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { // Checks that a field in a struct constructor (expression or pattern) is accessible. fn check_field( &self, - hir_id: hir::HirId, // ID of the field use use_ctxt: Span, // syntax context of the field name at the use site def: ty::AdtDef<'tcx>, // definition of the struct or enum field: &'tcx ty::FieldDef, @@ -944,8 +944,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { // definition of the field let ident = Ident::new(sym::dummy, use_ctxt); - let (_, def_id) = - self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id.owner.def_id); + let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), self.mod_id); !field.vis.is_accessible_from(def_id, self.tcx) } @@ -1018,7 +1017,6 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { adt: ty::AdtDef<'tcx>, variant: &'tcx ty::VariantDef, fields: &[hir::ExprField<'tcx>], - hir_id: hir::HirId, span: Span, struct_span: Span, ) { @@ -1026,11 +1024,11 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { for (vf_index, variant_field) in variant.fields.iter_enumerated() { let field = fields.iter().find(|f| self.typeck_results().field_index(f.hir_id) == vf_index); - let (hir_id, use_ctxt, span) = match field { - Some(field) => (field.hir_id, field.ident.span, field.span), - None => (hir_id, span, span), + let (use_ctxt, span) = match field { + Some(field) => (field.ident.span, field.span), + None => (span, span), }; - if self.check_field(hir_id, use_ctxt, adt, variant_field) { + if self.check_field(use_ctxt, adt, variant_field) { let name = match field { Some(field) => field.ident.name, None => variant_field.name, @@ -1064,31 +1062,16 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { // If the expression uses FRU we need to make sure all the unmentioned fields // are checked for privacy (RFC 736). Rather than computing the set of // unmentioned fields, just check them all. - self.check_expanded_fields( - adt, - variant, - fields, - base.hir_id, - base.span, - qpath.span(), - ); + self.check_expanded_fields(adt, variant, fields, base.span, qpath.span()); } hir::StructTailExpr::DefaultFields(span) => { - self.check_expanded_fields( - adt, - variant, - fields, - expr.hir_id, - span, - qpath.span(), - ); + self.check_expanded_fields(adt, variant, fields, span, qpath.span()); } hir::StructTailExpr::None | hir::StructTailExpr::NoneWithError(_) => { let mut failed_fields = vec![]; for field in fields { - let (hir_id, use_ctxt) = (field.hir_id, field.ident.span); let index = self.typeck_results().field_index(field.hir_id); - if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) { + if self.check_field(field.ident.span, adt, &variant.fields[index]) { failed_fields.push((field.ident.name, field.ident.span, true)); } } @@ -1107,9 +1090,8 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { let variant = adt.variant_of_res(res); let mut failed_fields = vec![]; for field in fields { - let (hir_id, use_ctxt) = (field.hir_id, field.ident.span); let index = self.typeck_results().field_index(field.hir_id); - if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) { + if self.check_field(field.ident.span, adt, &variant.fields[index]) { failed_fields.push((field.ident.name, field.ident.span, true)); } } @@ -1744,7 +1726,7 @@ pub fn provide(providers: &mut Providers) { fn check_mod_privacy(tcx: TyCtxt<'_>, mod_id: LocalModId) { // Check privacy of names not checked in previous compilation stages. - let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None }; + let mut visitor = NamePrivacyVisitor { tcx, mod_id, maybe_typeck_results: None }; tcx.hir_visit_item_likes_in_module(mod_id, &mut visitor); // Check privacy of explicitly written types and traits as well as 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 2a1f0e7935ea0..862834ca67676 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -348,7 +348,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let (adjusted_ident, def_scope) = self.tcx.adjust_ident_and_get_scope( field_ident, base_def.did(), - typeck_results.hir_owner.def_id, + self.tcx.parent_module_from_def_id(typeck_results.hir_owner.def_id), ); let Some((_, field_def)) =