diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:25 +0000 |
commit | 5363f350887b1e5b5dd21a86f88c8af9d7fea6da (patch) | |
tree | 35ca005eb6e0e9a1ba3bb5dbc033209ad445dc17 /compiler/rustc_middle/src/middle | |
parent | Adding debian version 1.66.0+dfsg1-1. (diff) | |
download | rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.tar.xz rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/middle')
-rw-r--r-- | compiler/rustc_middle/src/middle/codegen_fn_attrs.rs | 5 | ||||
-rw-r--r-- | compiler/rustc_middle/src/middle/lang_items.rs | 10 | ||||
-rw-r--r-- | compiler/rustc_middle/src/middle/privacy.rs | 209 |
3 files changed, 152 insertions, 72 deletions
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 45d33a165..bea884c85 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -26,8 +26,10 @@ pub struct CodegenFnAttrs { /// The `#[target_feature(enable = "...")]` attribute and the enabled /// features (only enabled features are supported right now). pub target_features: Vec<Symbol>, - /// The `#[linkage = "..."]` attribute and the value we found. + /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. pub linkage: Option<Linkage>, + /// The `#[linkage = "..."]` attribute on foreign items and the value we found. + pub import_linkage: Option<Linkage>, /// The `#[link_section = "..."]` attribute, or what executable section this /// should be placed in. pub link_section: Option<Symbol>, @@ -113,6 +115,7 @@ impl CodegenFnAttrs { link_ordinal: None, target_features: vec![], linkage: None, + import_linkage: None, link_section: None, no_sanitize: SanitizerSet::empty(), instruction_set: None, diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index 31c20fa14..343ea1f00 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -27,7 +27,10 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn fn_trait_kind_from_lang_item(self, id: DefId) -> Option<ty::ClosureKind> { + /// Given a [`DefId`] of a [`Fn`], [`FnMut`] or [`FnOnce`] traits, + /// returns a corresponding [`ty::ClosureKind`]. + /// For any other [`DefId`] return `None`. + pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> { let items = self.lang_items(); match Some(id) { x if x == items.fn_trait() => Some(ty::ClosureKind::Fn), @@ -37,8 +40,9 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn is_weak_lang_item(self, item_def_id: DefId) -> bool { - self.lang_items().is_weak_lang_item(item_def_id) + /// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits. + pub fn is_fn_trait(self, id: DefId) -> bool { + self.fn_trait_kind_from_def_id(id).is_some() } } diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 9c68c7504..fc08d58cc 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -1,12 +1,12 @@ //! A pass that checks to make sure private fields and methods aren't used //! outside their scopes. This pass will also generate a set of exported items //! which are available for use externally when compiled as a library. -use crate::ty::{DefIdTree, Visibility}; +use crate::ty::{DefIdTree, TyCtxt, Visibility}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; -use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::def_id::LocalDefId; use std::hash::Hash; /// Represents the levels of effective visibility an item can have. @@ -75,33 +75,33 @@ impl EffectiveVisibility { } /// Holds a map of effective visibilities for reachable HIR nodes. -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] pub struct EffectiveVisibilities<Id = LocalDefId> { map: FxHashMap<Id, EffectiveVisibility>, } -impl<Id: Hash + Eq + Copy> EffectiveVisibilities<Id> { - pub fn is_public_at_level(&self, id: Id, level: Level) -> bool { +impl EffectiveVisibilities { + pub fn is_public_at_level(&self, id: LocalDefId, level: Level) -> bool { self.effective_vis(id) .map_or(false, |effective_vis| effective_vis.is_public_at_level(level)) } /// See `Level::Reachable`. - pub fn is_reachable(&self, id: Id) -> bool { + pub fn is_reachable(&self, id: LocalDefId) -> bool { self.is_public_at_level(id, Level::Reachable) } /// See `Level::Reexported`. - pub fn is_exported(&self, id: Id) -> bool { + pub fn is_exported(&self, id: LocalDefId) -> bool { self.is_public_at_level(id, Level::Reexported) } /// See `Level::Direct`. - pub fn is_directly_public(&self, id: Id) -> bool { + pub fn is_directly_public(&self, id: LocalDefId) -> bool { self.is_public_at_level(id, Level::Direct) } - pub fn public_at_level(&self, id: Id) -> Option<Level> { + pub fn public_at_level(&self, id: LocalDefId) -> Option<Level> { self.effective_vis(id).and_then(|effective_vis| { for level in Level::all_levels() { if effective_vis.is_public_at_level(level) { @@ -112,31 +112,42 @@ impl<Id: Hash + Eq + Copy> EffectiveVisibilities<Id> { }) } - pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { - self.map.get(&id) - } - - pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> { - self.map.iter() - } - - pub fn map_id<OutId: Hash + Eq + Copy>( - &self, - f: impl Fn(Id) -> OutId, - ) -> EffectiveVisibilities<OutId> { - EffectiveVisibilities { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() } + // FIXME: Share code with `fn update`. + pub fn update_eff_vis( + &mut self, + def_id: LocalDefId, + eff_vis: &EffectiveVisibility, + tree: impl DefIdTree, + ) { + use std::collections::hash_map::Entry; + match self.map.entry(def_id) { + Entry::Occupied(mut occupied) => { + let old_eff_vis = occupied.get_mut(); + for l in Level::all_levels() { + let vis_at_level = eff_vis.at_level(l); + let old_vis_at_level = old_eff_vis.at_level_mut(l); + if vis_at_level != old_vis_at_level + && vis_at_level.is_at_least(*old_vis_at_level, tree) + { + *old_vis_at_level = *vis_at_level + } + } + old_eff_vis + } + Entry::Vacant(vacant) => vacant.insert(*eff_vis), + }; } pub fn set_public_at_level( &mut self, - id: Id, - default_vis: impl FnOnce() -> Visibility, + id: LocalDefId, + lazy_private_vis: impl FnOnce() -> Visibility, level: Level, ) { let mut effective_vis = self .effective_vis(id) .copied() - .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis())); + .unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis())); for l in Level::all_levels() { if l <= level { *effective_vis.at_level_mut(l) = Visibility::Public; @@ -144,61 +155,123 @@ impl<Id: Hash + Eq + Copy> EffectiveVisibilities<Id> { } self.map.insert(id, effective_vis); } + + pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) { + if !cfg!(debug_assertions) { + return; + } + for (&def_id, ev) in &self.map { + // More direct visibility levels can never go farther than less direct ones, + // neither of effective visibilities can go farther than nominal visibility, + // and all effective visibilities are larger or equal than private visibility. + let private_vis = Visibility::Restricted(tcx.parent_module_from_def_id(def_id)); + let span = tcx.def_span(def_id.to_def_id()); + if !ev.direct.is_at_least(private_vis, tcx) { + span_bug!(span, "private {:?} > direct {:?}", private_vis, ev.direct); + } + if !ev.reexported.is_at_least(ev.direct, tcx) { + span_bug!(span, "direct {:?} > reexported {:?}", ev.direct, ev.reexported); + } + if !ev.reachable.is_at_least(ev.reexported, tcx) { + span_bug!(span, "reexported {:?} > reachable {:?}", ev.reexported, ev.reachable); + } + if !ev.reachable_through_impl_trait.is_at_least(ev.reachable, tcx) { + span_bug!( + span, + "reachable {:?} > reachable_through_impl_trait {:?}", + ev.reachable, + ev.reachable_through_impl_trait + ); + } + let nominal_vis = tcx.visibility(def_id); + // FIXME: `rustc_privacy` is not yet updated for the new logic and can set + // effective visibilities that are larger than the nominal one. + if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early { + span_bug!( + span, + "{:?}: reachable_through_impl_trait {:?} > nominal {:?}", + def_id, + ev.reachable_through_impl_trait, + nominal_vis + ); + } + } + } +} + +pub trait IntoDefIdTree { + type Tree: DefIdTree; + fn tree(self) -> Self::Tree; } -impl<Id: Hash + Eq + Copy + Into<DefId>> EffectiveVisibilities<Id> { - // `parent_id` is not necessarily a parent in source code tree, - // it is the node from which the maximum effective visibility is inherited. - pub fn update( +impl<Id: Eq + Hash> EffectiveVisibilities<Id> { + pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> { + self.map.iter() + } + + pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { + self.map.get(&id) + } + + // FIXME: Share code with `fn update`. + pub fn effective_vis_or_private( + &mut self, + id: Id, + lazy_private_vis: impl FnOnce() -> Visibility, + ) -> &EffectiveVisibility { + self.map.entry(id).or_insert_with(|| EffectiveVisibility::from_vis(lazy_private_vis())) + } + + pub fn update<T: IntoDefIdTree>( &mut self, id: Id, nominal_vis: Visibility, - default_vis: impl FnOnce() -> Visibility, - parent_id: Id, + lazy_private_vis: impl FnOnce(T) -> (Visibility, T), + inherited_effective_vis: EffectiveVisibility, level: Level, - tree: impl DefIdTree, + mut into_tree: T, ) -> bool { let mut changed = false; - let mut current_effective_vis = self.effective_vis(id).copied().unwrap_or_else(|| { - if id.into().is_crate_root() { - EffectiveVisibility::from_vis(Visibility::Public) - } else { - EffectiveVisibility::from_vis(default_vis()) + let mut current_effective_vis = match self.map.get(&id).copied() { + Some(eff_vis) => eff_vis, + None => { + let private_vis; + (private_vis, into_tree) = lazy_private_vis(into_tree); + EffectiveVisibility::from_vis(private_vis) } - }); - if let Some(inherited_effective_vis) = self.effective_vis(parent_id) { - let mut inherited_effective_vis_at_prev_level = - *inherited_effective_vis.at_level(level); - let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; - for l in Level::all_levels() { - if level >= l { - let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l); - let current_effective_vis_at_level = current_effective_vis.at_level_mut(l); - // effective visibility for id shouldn't be recalculated if - // inherited from parent_id effective visibility isn't changed at next level - if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level - && level != l) - { - 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; + }; + let tree = into_tree.tree(); + + let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.at_level(level); + let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; + for l in Level::all_levels() { + if level >= l { + let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l); + let current_effective_vis_at_level = current_effective_vis.at_level_mut(l); + // effective visibility for id shouldn't be recalculated if + // inherited from parent_id effective visibility isn't changed at next level + if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level + && level != l) + { + 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; } } + self.map.insert(id, current_effective_vis); changed } |