Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Option<ErrorGuaranteed>>,
lowering_delegation_segment: bool,
}
Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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())
Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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>;

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<Ident>,
Expand Down Expand Up @@ -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()
Expand Down
55 changes: 18 additions & 37 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -2765,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);
Expand Down Expand Up @@ -3244,7 +3239,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()))
Expand All @@ -3255,9 +3249,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::<Vec<_>>();
let mut candidate_fields: Vec<_> = found_fields
.into_iter()
Expand All @@ -3267,8 +3259,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&|candidate_field, _| candidate_field == field,
candidate_field,
vec![],
mod_id,
expr.hir_id,
)
})
.map(|mut field_path| {
Expand Down Expand Up @@ -3329,8 +3319,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
span: Span,
base_ty: Ty<'tcx>,
mod_id: DefId,
hir_id: HirId,
) -> Vec<Vec<(Ident, Ty<'tcx>)>> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);

Expand All @@ -3354,15 +3342,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<T>`.
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)
Expand Down Expand Up @@ -3394,15 +3385,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<Ident>,
mod_id: DefId,
hir_id: HirId,
) -> Option<Vec<Ident>> {
if field_path.len() > 3 {
// For compile-time reasons and to avoid infinite recursion we only check for fields
Expand All @@ -3413,21 +3402,16 @@ 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(
span,
matches,
field,
field_path.clone(),
mod_id,
hir_id,
) {
return Some(field_path);
}
Expand Down Expand Up @@ -3806,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
Expand Down Expand Up @@ -3861,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;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()) });
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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) => {
Expand Down
9 changes: 2 additions & 7 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 4 additions & 14 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -3207,13 +3206,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return_type: Option<Ty<'tcx>>,
) {
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();
Expand Down Expand Up @@ -3248,8 +3241,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
},
candidate_field,
vec![],
mod_id,
expr.hir_id,
)
})
.map(|field_path| {
Expand Down Expand Up @@ -3999,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| {
Expand Down Expand Up @@ -4057,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);
}
Expand Down
Loading
Loading