1
Fork 0

Split up privacy checking so privacy_access_levels only does computations required for AccessLevels

This commit is contained in:
John Kåre Alsaker 2019-02-23 16:40:15 +01:00
parent f22dca0a1b
commit d5bb71c9f1
7 changed files with 89 additions and 75 deletions

View file

@ -456,6 +456,7 @@ define_dep_nodes!( <'tcx>
[eval_always] CoherenceInherentImplOverlapCheck, [eval_always] CoherenceInherentImplOverlapCheck,
[] CoherenceCheckTrait(DefId), [] CoherenceCheckTrait(DefId),
[eval_always] PrivacyAccessLevels(CrateNum), [eval_always] PrivacyAccessLevels(CrateNum),
[eval_always] CheckPrivacy(CrateNum),
[eval_always] Analysis(CrateNum), [eval_always] Analysis(CrateNum),
// Represents the MIR for a fn; also used as the task node for // Represents the MIR for a fn; also used as the task node for

View file

@ -369,6 +369,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::privacy_access_levels<'tcx> {
} }
} }
impl<'tcx> QueryDescription<'tcx> for queries::check_privacy<'tcx> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"privacy checking".into()
}
}
impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"type-checking all item bodies".into() "type-checking all item bodies".into()

View file

@ -350,8 +350,9 @@ define_queries! { <'tcx>
[] fn check_match: CheckMatch(DefId) [] fn check_match: CheckMatch(DefId)
-> Result<(), ErrorReported>, -> Result<(), ErrorReported>,
/// Performs the privacy check and computes "access levels". /// Performs part of the privacy check and computes "access levels".
[] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Lrc<AccessLevels>, [] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Lrc<AccessLevels>,
[] fn check_privacy: CheckPrivacy(CrateNum) -> (),
}, },
Other { Other {

View file

@ -1251,6 +1251,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
force!(crate_inherent_impls_overlap_check, LOCAL_CRATE) force!(crate_inherent_impls_overlap_check, LOCAL_CRATE)
}, },
DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); } DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
DepKind::CheckPrivacy => { force!(check_privacy, LOCAL_CRATE); }
DepKind::MirBuilt => { force!(mir_built, def_id!()); } DepKind::MirBuilt => { force!(mir_built, def_id!()); }
DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); } DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
DepKind::MirConst => { force!(mir_const, def_id!()); } DepKind::MirConst => { force!(mir_const, def_id!()); }

View file

@ -21,7 +21,7 @@ use rustc_borrowck as borrowck;
use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
use rustc_incremental; use rustc_incremental;
use rustc_metadata::creader::CrateLoader; use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore}; use rustc_metadata::cstore::{self, CStore};
@ -277,9 +277,13 @@ fn analysis<'tcx>(
} }
time(sess, "misc checking", || { time(sess, "misc checking", || {
parallel!({
time(sess, "privacy access levels", || {
tcx.ensure().privacy_access_levels(LOCAL_CRATE);
});
parallel!({ parallel!({
time(sess, "privacy checking", || { time(sess, "privacy checking", || {
rustc_privacy::check_crate(tcx) tcx.ensure().check_privacy(LOCAL_CRATE);
}); });
}, { }, {
time(sess, "death checking", || middle::dead::check_crate(tcx)); time(sess, "death checking", || middle::dead::check_crate(tcx));
@ -290,6 +294,13 @@ fn analysis<'tcx>(
}, { }, {
time(sess, "lint checking", || lint::check_crate(tcx)); time(sess, "lint checking", || lint::check_crate(tcx));
}); });
}, {
time(sess, "privacy checking modules", || {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
});
});
});
}); });
Ok(()) Ok(())

View file

@ -1760,19 +1760,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
pub fn provide(providers: &mut Providers<'_>) { pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers { *providers = Providers {
privacy_access_levels, privacy_access_levels,
check_privacy,
check_mod_privacy, check_mod_privacy,
..*providers ..*providers
}; };
} }
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Lrc<AccessLevels> {
tcx.privacy_access_levels(LOCAL_CRATE)
}
fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
let empty_tables = ty::TypeckTables::empty(None); let empty_tables = ty::TypeckTables::empty(None);
// Check privacy of names not checked in previous compilation stages. // Check privacy of names not checked in previous compilation stages.
let mut visitor = NamePrivacyVisitor { let mut visitor = NamePrivacyVisitor {
tcx, tcx,
@ -1803,18 +1799,6 @@ fn privacy_access_levels<'tcx>(
) -> Lrc<AccessLevels> { ) -> Lrc<AccessLevels> {
assert_eq!(krate, LOCAL_CRATE); assert_eq!(krate, LOCAL_CRATE);
let krate = tcx.hir().krate();
for &module in krate.modules.keys() {
tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
}
let private_crates: FxHashSet<CrateNum> = tcx.sess.opts.extern_private.iter()
.flat_map(|c| {
tcx.crates().iter().find(|&&krate| &tcx.crate_name(krate) == c).cloned()
}).collect();
// Build up a set of all exported items in the AST. This is a set of all // Build up a set of all exported items in the AST. This is a set of all
// items which are reachable from external crates based on visibility. // items which are reachable from external crates based on visibility.
let mut visitor = EmbargoVisitor { let mut visitor = EmbargoVisitor {
@ -1824,7 +1808,7 @@ fn privacy_access_levels<'tcx>(
changed: false, changed: false,
}; };
loop { loop {
intravisit::walk_crate(&mut visitor, krate); intravisit::walk_crate(&mut visitor, tcx.hir().krate());
if visitor.changed { if visitor.changed {
visitor.changed = false; visitor.changed = false;
} else { } else {
@ -1833,16 +1817,24 @@ fn privacy_access_levels<'tcx>(
} }
visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public)); visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public));
{ Lrc::new(visitor.access_levels)
}
fn check_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, krate: CrateNum) {
assert_eq!(krate, LOCAL_CRATE);
let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
let krate = tcx.hir().krate();
let mut visitor = ObsoleteVisiblePrivateTypesVisitor { let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
tcx, tcx,
access_levels: &visitor.access_levels, access_levels: &access_levels,
in_variant: false, in_variant: false,
old_error_set: Default::default(), old_error_set: Default::default(),
}; };
intravisit::walk_crate(&mut visitor, krate); intravisit::walk_crate(&mut visitor, krate);
let has_pub_restricted = { let has_pub_restricted = {
let mut pub_restricted_visitor = PubRestrictedVisitor { let mut pub_restricted_visitor = PubRestrictedVisitor {
tcx, tcx,
@ -1852,6 +1844,11 @@ fn privacy_access_levels<'tcx>(
pub_restricted_visitor.has_pub_restricted pub_restricted_visitor.has_pub_restricted
}; };
let private_crates: FxHashSet<CrateNum> = tcx.sess.opts.extern_private.iter()
.flat_map(|c| {
tcx.crates().iter().find(|&&krate| &tcx.crate_name(krate) == c).cloned()
}).collect();
// Check for private types and traits in public interfaces. // Check for private types and traits in public interfaces.
let mut visitor = PrivateItemsInPublicInterfacesVisitor { let mut visitor = PrivateItemsInPublicInterfacesVisitor {
tcx, tcx,
@ -1862,7 +1859,4 @@ fn privacy_access_levels<'tcx>(
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
} }
Lrc::new(visitor.access_levels)
}
__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS } __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }

View file

@ -1,3 +1,21 @@
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-inferred-type.rs:61:36
|
LL | struct Priv;
| - `m::Priv` declared as private
...
LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
| ^^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0446]: private type `adjust::S2` in public interface
--> $DIR/private-inferred-type.rs:83:9
|
LL | struct S2;
| - `adjust::S2` declared as private
...
LL | type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
| ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
error: type `m::Priv` is private error: type `m::Priv` is private
--> $DIR/private-inferred-type.rs:97:9 --> $DIR/private-inferred-type.rs:97:9
| |
@ -202,24 +220,6 @@ error: type `m::Priv` is private
LL | match a { //~ ERROR type `m::Priv` is private LL | match a { //~ ERROR type `m::Priv` is private
| ^ | ^
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-inferred-type.rs:61:36
|
LL | struct Priv;
| - `m::Priv` declared as private
...
LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
| ^^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0446]: private type `adjust::S2` in public interface
--> $DIR/private-inferred-type.rs:83:9
|
LL | struct S2;
| - `adjust::S2` declared as private
...
LL | type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
| ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
error: aborting due to 33 previous errors error: aborting due to 33 previous errors
For more information about this error, try `rustc --explain E0446`. For more information about this error, try `rustc --explain E0446`.