Skip to content

Commit

Permalink
Auto merge of #78077 - petrochenkov:qvis, r=davidtwco
Browse files Browse the repository at this point in the history
Calculate visibilities once in resolve

Then use them through a query based on resolver outputs.

Item visibilities were previously calculated in three places - initially in `rustc_resolve`, then in `rustc_privacy` during type privacy checkin, and then in `rustc_metadata` during metadata encoding.
The visibility logic is not entirely trivial, especially for things like constructors or enum variants, and all of it was duplicated.

This PR deduplicates all the visibility calculations, visibilities are determined once during early name resolution and then stored in `ResolverOutputs` and are later available through `tcx` as a query `tcx.visibility(def_id)`.
(This query existed previously, but only worked for other crates.)

Some special cases (e.g. visibilities for closure types, which are needed for type privacy checking) are not processed in resolve, but deferred and performed directly in the query instead.
  • Loading branch information
bors committed Oct 21, 2020
2 parents 1d27267 + cee5521 commit 1eaadeb
Show file tree
Hide file tree
Showing 26 changed files with 322 additions and 408 deletions.
9 changes: 0 additions & 9 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2381,15 +2381,6 @@ impl VisibilityKind<'_> {
VisibilityKind::Crate(..) | VisibilityKind::Restricted { .. } => true,
}
}

pub fn descr(&self) -> &'static str {
match *self {
VisibilityKind::Public => "public",
VisibilityKind::Inherited => "private",
VisibilityKind::Crate(..) => "crate-visible",
VisibilityKind::Restricted { .. } => "restricted",
}
}
}

#[derive(Debug, HashStable_Generic)]
Expand Down
69 changes: 13 additions & 56 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
use rustc_serialize::{opaque, Encodable, Encoder};
use rustc_session::config::CrateType;
use rustc_span::hygiene::{ExpnDataEncodeMode, HygieneEncodeContext};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
use rustc_target::abi::VariantIdx;
Expand Down Expand Up @@ -436,8 +435,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

fn encode_info_for_items(&mut self) {
let krate = self.tcx.hir().krate();
let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public };
self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs, &vis);
self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs);

// Proc-macro crates only export proc-macro items, which are looked
// up using `proc_macro_data`
Expand Down Expand Up @@ -739,12 +737,8 @@ impl EncodeContext<'a, 'tcx> {
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
};

let enum_id = tcx.hir().local_def_id_to_hir_id(def.did.expect_local());
let enum_vis = &tcx.hir().expect_item(enum_id).vis;

record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
record!(self.tables.visibility[def_id] <-
ty::Visibility::from_hir(enum_vis, enum_id, self.tcx));
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
record!(self.tables.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
Expand Down Expand Up @@ -785,17 +779,8 @@ impl EncodeContext<'a, 'tcx> {
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
};

// Variant constructors have the same visibility as the parent enums, unless marked as
// non-exhaustive, in which case they are lowered to `pub(crate)`.
let enum_id = tcx.hir().local_def_id_to_hir_id(def.did.expect_local());
let enum_vis = &tcx.hir().expect_item(enum_id).vis;
let mut ctor_vis = ty::Visibility::from_hir(enum_vis, enum_id, tcx);
if variant.is_field_list_non_exhaustive() && ctor_vis == ty::Visibility::Public {
ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
}

record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
record!(self.tables.visibility[def_id] <- ctor_vis);
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
self.encode_stability(def_id);
self.encode_deprecation(def_id);
Expand All @@ -811,13 +796,7 @@ impl EncodeContext<'a, 'tcx> {
self.encode_promoted_mir(def_id.expect_local());
}

fn encode_info_for_mod(
&mut self,
id: hir::HirId,
md: &hir::Mod<'_>,
attrs: &[ast::Attribute],
vis: &hir::Visibility<'_>,
) {
fn encode_info_for_mod(&mut self, id: hir::HirId, md: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
let tcx = self.tcx;
let local_def_id = tcx.hir().local_def_id(id);
let def_id = local_def_id.to_def_id();
Expand Down Expand Up @@ -850,7 +829,7 @@ impl EncodeContext<'a, 'tcx> {
};

record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
record!(self.tables.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx));
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
record!(self.tables.attributes[def_id] <- attrs);
if self.is_proc_macro {
Expand Down Expand Up @@ -881,7 +860,7 @@ impl EncodeContext<'a, 'tcx> {
let variant_data = tcx.hir().expect_variant_data(variant_id);

record!(self.tables.kind[def_id] <- EntryKind::Field);
record!(self.tables.visibility[def_id] <- field.vis);
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
record!(self.tables.attributes[def_id] <- variant_data.fields()[field_index].attrs);
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
Expand All @@ -906,25 +885,8 @@ impl EncodeContext<'a, 'tcx> {
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
};

let struct_id = tcx.hir().local_def_id_to_hir_id(adt_def.did.expect_local());
let struct_vis = &tcx.hir().expect_item(struct_id).vis;
let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
for field in &variant.fields {
if ctor_vis.is_at_least(field.vis, tcx) {
ctor_vis = field.vis;
}
}

// If the structure is marked as non_exhaustive then lower the visibility
// to within the crate.
if adt_def.non_enum_variant().is_field_list_non_exhaustive()
&& ctor_vis == ty::Visibility::Public
{
ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
}

record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr));
record!(self.tables.visibility[def_id] <- ctor_vis);
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
self.encode_stability(def_id);
Expand Down Expand Up @@ -1030,7 +992,7 @@ impl EncodeContext<'a, 'tcx> {
EntryKind::AssocType(container)
}
});
record!(self.tables.visibility[def_id] <- trait_item.vis);
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- ast_item.span);
record!(self.tables.attributes[def_id] <- ast_item.attrs);
self.encode_ident_span(def_id, ast_item.ident);
Expand Down Expand Up @@ -1112,7 +1074,7 @@ impl EncodeContext<'a, 'tcx> {
}
ty::AssocKind::Type => EntryKind::AssocType(container)
});
record!(self.tables.visibility[def_id] <- impl_item.vis);
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- ast_item.span);
record!(self.tables.attributes[def_id] <- ast_item.attrs);
self.encode_ident_span(def_id, impl_item.ident);
Expand Down Expand Up @@ -1261,7 +1223,7 @@ impl EncodeContext<'a, 'tcx> {
EntryKind::Fn(self.lazy(data))
}
hir::ItemKind::Mod(ref m) => {
return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis);
return self.encode_info_for_mod(item.hir_id, m, &item.attrs);
}
hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
Expand Down Expand Up @@ -1352,8 +1314,7 @@ impl EncodeContext<'a, 'tcx> {
hir::ItemKind::ExternCrate(_) |
hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
});
record!(self.tables.visibility[def_id] <-
ty::Visibility::from_hir(&item.vis, item.hir_id, tcx));
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
record!(self.tables.attributes[def_id] <- item.attrs);
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
Expand Down Expand Up @@ -1470,7 +1431,7 @@ impl EncodeContext<'a, 'tcx> {
fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
let def_id = self.tcx.hir().local_def_id(macro_def.hir_id).to_def_id();
record!(self.tables.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- macro_def.span);
record!(self.tables.attributes[def_id] <- macro_def.attrs);
self.encode_ident_span(def_id, macro_def.ident);
Expand All @@ -1480,7 +1441,6 @@ impl EncodeContext<'a, 'tcx> {

fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) {
record!(self.tables.kind[def_id] <- kind);
record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
if encode_type {
self.encode_item_type(def_id);
Expand All @@ -1505,7 +1465,6 @@ impl EncodeContext<'a, 'tcx> {

_ => bug!("closure that is neither generator nor closure"),
});
record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public);
record!(self.tables.span[def_id.to_def_id()] <- self.tcx.def_span(def_id));
record!(self.tables.attributes[def_id.to_def_id()] <- &self.tcx.get_attrs(def_id.to_def_id())[..]);
self.encode_item_type(def_id.to_def_id());
Expand All @@ -1525,7 +1484,6 @@ impl EncodeContext<'a, 'tcx> {
let qualifs = self.tcx.mir_const_qualif(def_id);

record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::AnonConst(qualifs, const_data));
record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public);
record!(self.tables.span[def_id.to_def_id()] <- self.tcx.def_span(def_id));
self.encode_item_type(def_id.to_def_id());
self.encode_generics(def_id.to_def_id());
Expand Down Expand Up @@ -1762,8 +1720,7 @@ impl EncodeContext<'a, 'tcx> {
hir::ForeignItemKind::Static(_, hir::Mutability::Not) => EntryKind::ForeignImmStatic,
hir::ForeignItemKind::Type => EntryKind::ForeignType,
});
record!(self.tables.visibility[def_id] <-
ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx));
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
record!(self.tables.span[def_id] <- nitem.span);
record!(self.tables.attributes[def_id] <- nitem.attrs);
self.encode_ident_span(def_id, nitem.ident);
Expand Down
22 changes: 5 additions & 17 deletions compiler/rustc_middle/src/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,24 +256,12 @@ pub enum EvalResult {
}

// See issue #38412.
fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool {
// Check if `def_id` is a trait method.
match tcx.def_kind(def_id) {
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
if let ty::TraitContainer(trait_def_id) = tcx.associated_item(def_id).container {
// Trait methods do not declare visibility (even
// for visibility info in cstore). Use containing
// trait instead, so methods of `pub` traits are
// themselves considered `pub`.
def_id = trait_def_id;
}
}
_ => {}
fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
if tcx.def_kind(def_id) == DefKind::TyParam {
// Have no visibility, considered public for the purpose of this check.
return false;
}

let visibility = tcx.visibility(def_id);

match visibility {
match tcx.visibility(def_id) {
// Must check stability for `pub` items.
ty::Visibility::Public => false,

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,7 @@ rustc_queries! {

TypeChecking {
query visibility(def_id: DefId) -> ty::Visibility {
eval_always
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
}
}
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::ty::{
ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntVar,
IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
TyVid, TypeAndMut,
TyVid, TypeAndMut, Visibility,
};
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
Expand Down Expand Up @@ -911,6 +911,9 @@ pub struct GlobalCtxt<'tcx> {
/// Common consts, pre-interned for your convenience.
pub consts: CommonConsts<'tcx>,

/// Visibilities produced by resolver.
pub visibilities: FxHashMap<LocalDefId, Visibility>,

/// Resolutions of `extern crate` items produced by resolver.
extern_crate_map: FxHashMap<LocalDefId, CrateNum>,

Expand Down Expand Up @@ -1124,6 +1127,7 @@ impl<'tcx> TyCtxt<'tcx> {
types: common_types,
lifetimes: common_lifetimes,
consts: common_consts,
visibilities: resolutions.visibilities,
extern_crate_map: resolutions.extern_crate_map,
trait_map,
export_map: resolutions.export_map,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ mod sty;
pub struct ResolverOutputs {
pub definitions: rustc_hir::definitions::Definitions,
pub cstore: Box<CrateStoreDyn>,
pub visibilities: FxHashMap<LocalDefId, Visibility>,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
Expand Down
Loading

0 comments on commit 1eaadeb

Please sign in to comment.