1
Fork 0

Auto merge of #78077 - petrochenkov:qvis, r=davidtwco

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.
This commit is contained in:
bors 2020-10-21 20:23:26 +00:00
commit 1eaadebb3d
26 changed files with 323 additions and 409 deletions

View file

@ -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,

View file

@ -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) }
}
}

View file

@ -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;
@ -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>,
@ -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,

View file

@ -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)>,