Auto merge of #103158 - Bryanskiy:resolve_perf, r=petrochenkov

Perf improvements for effective visibility calculating

related to https://github.com/rust-lang/rust/pull/102026
r? `@petrochenkov`
This commit is contained in:
bors 2022-10-26 02:30:18 +00:00
commit a5406feb1c
5 changed files with 57 additions and 53 deletions

View File

@ -69,21 +69,7 @@ impl EffectiveVisibility {
self.get(tag).is_public() self.get(tag).is_public()
} }
fn update(&mut self, vis: Visibility, tag: AccessLevel, tree: impl DefIdTree) -> bool { pub fn from_vis(vis: Visibility) -> EffectiveVisibility {
let mut changed = false;
for level in AccessLevel::all_levels() {
if level <= tag {
let current_effective_vis = self.get_mut(level);
if *current_effective_vis != vis && vis.is_at_least(*current_effective_vis, tree) {
changed = true;
*current_effective_vis = vis;
}
}
}
changed
}
fn from_vis(vis: Visibility) -> EffectiveVisibility {
EffectiveVisibility { EffectiveVisibility {
public: vis, public: vis,
exported: vis, exported: vis,
@ -173,33 +159,49 @@ impl<Id: Hash + Eq + Copy + Into<DefId>> AccessLevels<Id> {
parent_id: Id, parent_id: Id,
tag: AccessLevel, tag: AccessLevel,
tree: impl DefIdTree, tree: impl DefIdTree,
) -> Result<bool, ()> { ) -> bool {
let mut changed = false; let mut changed = false;
let mut current_effective_vis = self let mut current_effective_vis = self.get_effective_vis(id).copied().unwrap_or_else(|| {
.get_effective_vis(id) if id.into().is_crate_root() {
.copied() EffectiveVisibility::from_vis(Visibility::Public)
.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis())); } else {
EffectiveVisibility::from_vis(default_vis())
}
});
if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) { if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) {
let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.get(tag);
let mut calculated_effective_vis = inherited_effective_vis_at_prev_level;
for level in AccessLevel::all_levels() { for level in AccessLevel::all_levels() {
if tag >= level { if tag >= level {
let inherited_effective_vis_at_level = *inherited_effective_vis.get(level); let inherited_effective_vis_at_level = *inherited_effective_vis.get(level);
let calculated_effective_vis = let current_effective_vis_at_level = current_effective_vis.get_mut(level);
if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) { // effective visibility for id shouldn't be recalculated if
inherited_effective_vis_at_level // inherited from parent_id effective visibility isn't changed at next level
} else { if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
nominal_vis && tag != level)
}; {
changed |= current_effective_vis.update(calculated_effective_vis, level, tree); calculated_effective_vis =
if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
inherited_effective_vis_at_level
} else {
nominal_vis
};
}
// effective visibility can't be decreased at next update call for the
// same id
if *current_effective_vis_at_level != calculated_effective_vis
&& calculated_effective_vis
.is_at_least(*current_effective_vis_at_level, tree)
{
changed = true;
*current_effective_vis_at_level = calculated_effective_vis;
}
inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level;
} }
} }
} else {
if !id.into().is_crate_root() {
return Err(());
}
changed |= current_effective_vis.update(Visibility::Public, AccessLevel::Public, tree);
} }
self.map.insert(id, current_effective_vis); self.map.insert(id, current_effective_vis);
Ok(changed) changed
} }
} }

View File

@ -922,9 +922,9 @@ pub struct TestReachabilityVisitor<'tcx, 'a> {
impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
fn access_level_diagnostic(&mut self, def_id: LocalDefId) { fn access_level_diagnostic(&mut self, def_id: LocalDefId) {
if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) { if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) {
let mut error_msg = String::new();
let span = self.tcx.def_span(def_id.to_def_id());
if let Some(effective_vis) = self.access_levels.get_effective_vis(def_id) { if let Some(effective_vis) = self.access_levels.get_effective_vis(def_id) {
let mut error_msg = String::new();
let span = self.tcx.def_span(def_id.to_def_id());
for level in AccessLevel::all_levels() { for level in AccessLevel::all_levels() {
let vis_str = match effective_vis.get(level) { let vis_str = match effective_vis.get(level) {
ty::Visibility::Restricted(restricted_id) => { ty::Visibility::Restricted(restricted_id) => {
@ -943,8 +943,10 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
} }
error_msg.push_str(&format!("{:?}: {}", level, vis_str)); error_msg.push_str(&format!("{:?}: {}", level, vis_str));
} }
self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg }); } else {
error_msg.push_str("not in the table");
} }
self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg });
} }
} }
} }

View File

@ -96,10 +96,18 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
parent_id: LocalDefId, parent_id: LocalDefId,
tag: AccessLevel, tag: AccessLevel,
) { ) {
let module_id = self
.r
.get_nearest_non_block_module(def_id.to_def_id())
.nearest_parent_mod()
.expect_local();
if nominal_vis == Visibility::Restricted(module_id)
|| self.r.visibilities[&parent_id] == Visibility::Restricted(module_id)
{
return;
}
let mut access_levels = std::mem::take(&mut self.r.access_levels); let mut access_levels = std::mem::take(&mut self.r.access_levels);
let module_id = self.changed |= access_levels.update(
self.r.get_nearest_non_block_module(def_id.to_def_id()).def_id().expect_local();
let res = access_levels.update(
def_id, def_id,
nominal_vis, nominal_vis,
|| Visibility::Restricted(module_id), || Visibility::Restricted(module_id),
@ -107,14 +115,6 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
tag, tag,
&*self.r, &*self.r,
); );
if let Ok(changed) = res {
self.changed |= changed;
} else {
self.r.session.delay_span_bug(
self.r.opt_span(def_id.to_def_id()).unwrap(),
"Can't update effective visibility",
);
}
self.r.access_levels = access_levels; self.r.access_levels = access_levels;
} }
} }

View File

@ -17,12 +17,12 @@ mod outer { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(c
} }
#[rustc_effective_visibility] #[rustc_effective_visibility]
struct PrivStruct; //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) struct PrivStruct; //~ ERROR not in the table
#[rustc_effective_visibility] #[rustc_effective_visibility]
pub union PubUnion { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub pub union PubUnion { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
#[rustc_effective_visibility] #[rustc_effective_visibility]
a: u8, //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) a: u8, //~ ERROR not in the table
#[rustc_effective_visibility] #[rustc_effective_visibility]
pub b: u8, //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub pub b: u8, //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
} }
@ -38,13 +38,13 @@ mod outer { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(c
} }
#[rustc_effective_visibility] #[rustc_effective_visibility]
macro_rules! none_macro { //~ Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) macro_rules! none_macro { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate)
() => {}; () => {};
} }
#[macro_export] #[macro_export]
#[rustc_effective_visibility] #[rustc_effective_visibility]
macro_rules! public_macro { //~ Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub macro_rules! public_macro { //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
() => {}; () => {};
} }

View File

@ -22,7 +22,7 @@ error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait
LL | pub trait PubTrait { LL | pub trait PubTrait {
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) error: not in the table
--> $DIR/access_levels.rs:20:9 --> $DIR/access_levels.rs:20:9
| |
LL | struct PrivStruct; LL | struct PrivStruct;
@ -34,7 +34,7 @@ error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait
LL | pub union PubUnion { LL | pub union PubUnion {
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) error: not in the table
--> $DIR/access_levels.rs:25:13 --> $DIR/access_levels.rs:25:13
| |
LL | a: u8, LL | a: u8,