Auto merge of #102026 - Bryanskiy:resolve_update, r=petrochenkov · rust-lang/rust@b8b5cae (original) (raw)
1
1
`//! A pass that checks to make sure private fields and methods aren't used
`
2
2
`//! outside their scopes. This pass will also generate a set of exported items
`
3
3
`//! which are available for use externally when compiled as a library.
`
4
``
`-
use crate::ty::Visibility;
`
``
4
`+
use crate::ty::{DefIdTree, Visibility};
`
5
5
`use rustc_data_structures::fx::FxHashMap;
`
6
6
`use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
`
7
7
`use rustc_macros::HashStable;
`
8
8
`use rustc_query_system::ich::StableHashingContext;
`
9
``
`-
use rustc_span::def_id::LocalDefId;
`
``
9
`+
use rustc_span::def_id::{DefId, LocalDefId};
`
10
10
`use std::hash::Hash;
`
11
11
``
12
12
`/// Represents the levels of accessibility an item can have.
`
`@@ -27,26 +27,36 @@ pub enum AccessLevel {
`
27
27
`Public,
`
28
28
`}
`
29
29
``
30
``
`-
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Default)]
`
``
30
`+
impl AccessLevel {
`
``
31
`+
pub fn all_levels() -> [AccessLevel; 4] {
`
``
32
`+
[
`
``
33
`+
AccessLevel::Public,
`
``
34
`+
AccessLevel::Exported,
`
``
35
`+
AccessLevel::Reachable,
`
``
36
`+
AccessLevel::ReachableFromImplTrait,
`
``
37
`+
]
`
``
38
`+
}
`
``
39
`+
}
`
``
40
+
``
41
`+
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
`
31
42
`pub struct EffectiveVisibility {
`
32
``
`-
public: Option,
`
33
``
`-
exported: Option,
`
34
``
`-
reachable: Option,
`
35
``
`-
reachable_from_impl_trait: Option,
`
``
43
`+
public: Visibility,
`
``
44
`+
exported: Visibility,
`
``
45
`+
reachable: Visibility,
`
``
46
`+
reachable_from_impl_trait: Visibility,
`
36
47
`}
`
37
48
``
38
49
`impl EffectiveVisibility {
`
39
``
`-
pub fn get(&self, tag: AccessLevel) -> Option<&Visibility> {
`
``
50
`+
pub fn get(&self, tag: AccessLevel) -> &Visibility {
`
40
51
`match tag {
`
41
52
`AccessLevel::Public => &self.public,
`
42
53
`AccessLevel::Exported => &self.exported,
`
43
54
`AccessLevel::Reachable => &self.reachable,
`
44
55
`AccessLevel::ReachableFromImplTrait => &self.reachable_from_impl_trait,
`
45
56
`}
`
46
``
`-
.as_ref()
`
47
57
`}
`
48
58
``
49
``
`-
fn get_mut(&mut self, tag: AccessLevel) -> &mut Option {
`
``
59
`+
fn get_mut(&mut self, tag: AccessLevel) -> &mut Visibility {
`
50
60
`match tag {
`
51
61
`AccessLevel::Public => &mut self.public,
`
52
62
`AccessLevel::Exported => &mut self.exported,
`
`@@ -56,7 +66,30 @@ impl EffectiveVisibility {
`
56
66
`}
`
57
67
``
58
68
`pub fn is_public_at_level(&self, tag: AccessLevel) -> bool {
`
59
``
`-
self.get(tag).map_or(false, |vis| vis.is_public())
`
``
69
`+
self.get(tag).is_public()
`
``
70
`+
}
`
``
71
+
``
72
`+
fn update(&mut self, vis: Visibility, tag: AccessLevel, tree: impl DefIdTree) -> bool {
`
``
73
`+
let mut changed = false;
`
``
74
`+
for level in AccessLevel::all_levels() {
`
``
75
`+
if level <= tag {
`
``
76
`+
let current_effective_vis = self.get_mut(level);
`
``
77
`+
if *current_effective_vis != vis && vis.is_at_least(*current_effective_vis, tree) {
`
``
78
`+
changed = true;
`
``
79
`+
*current_effective_vis = vis;
`
``
80
`+
}
`
``
81
`+
}
`
``
82
`+
}
`
``
83
`+
changed
`
``
84
`+
}
`
``
85
+
``
86
`+
fn from_vis(vis: Visibility) -> EffectiveVisibility {
`
``
87
`+
EffectiveVisibility {
`
``
88
`+
public: vis,
`
``
89
`+
exported: vis,
`
``
90
`+
reachable: vis,
`
``
91
`+
reachable_from_impl_trait: vis,
`
``
92
`+
}
`
60
93
`}
`
61
94
`}
`
62
95
``
`@@ -89,12 +122,7 @@ impl<Id: Hash + Eq + Copy> AccessLevels {
`
89
122
``
90
123
`pub fn get_access_level(&self, id: Id) -> Option {
`
91
124
`self.get_effective_vis(id).and_then(|effective_vis| {
`
92
``
`-
for level in [
`
93
``
`-
AccessLevel::Public,
`
94
``
`-
AccessLevel::Exported,
`
95
``
`-
AccessLevel::Reachable,
`
96
``
`-
AccessLevel::ReachableFromImplTrait,
`
97
``
`-
] {
`
``
125
`+
for level in AccessLevel::all_levels() {
`
98
126
`if effective_vis.is_public_at_level(level) {
`
99
127
`return Some(level);
`
100
128
`}
`
`@@ -103,21 +131,6 @@ impl<Id: Hash + Eq + Copy> AccessLevels {
`
103
131
`})
`
104
132
`}
`
105
133
``
106
``
`-
pub fn set_access_level(&mut self, id: Id, tag: AccessLevel) {
`
107
``
`-
let mut effective_vis = self.get_effective_vis(id).copied().unwrap_or_default();
`
108
``
`-
for level in [
`
109
``
`-
AccessLevel::Public,
`
110
``
`-
AccessLevel::Exported,
`
111
``
`-
AccessLevel::Reachable,
`
112
``
`-
AccessLevel::ReachableFromImplTrait,
`
113
``
`-
] {
`
114
``
`-
if level <= tag {
`
115
``
`-
*effective_vis.get_mut(level) = Some(Visibility::Public);
`
116
``
`-
}
`
117
``
`-
}
`
118
``
`-
self.map.insert(id, effective_vis);
`
119
``
`-
}
`
120
``
-
121
134
`pub fn get_effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> {
`
122
135
`self.map.get(&id)
`
123
136
`}
`
`@@ -129,6 +142,65 @@ impl<Id: Hash + Eq + Copy> AccessLevels {
`
129
142
`pub fn map_id<OutId: Hash + Eq + Copy>(&self, f: impl Fn(Id) -> OutId) -> AccessLevels {
`
130
143
`AccessLevels { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() }
`
131
144
`}
`
``
145
+
``
146
`+
pub fn set_access_level(
`
``
147
`+
&mut self,
`
``
148
`+
id: Id,
`
``
149
`+
default_vis: impl FnOnce() -> Visibility,
`
``
150
`+
tag: AccessLevel,
`
``
151
`+
) {
`
``
152
`+
let mut effective_vis = self
`
``
153
`+
.get_effective_vis(id)
`
``
154
`+
.copied()
`
``
155
`+
.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
`
``
156
`+
for level in AccessLevel::all_levels() {
`
``
157
`+
if level <= tag {
`
``
158
`+
*effective_vis.get_mut(level) = Visibility::Public;
`
``
159
`+
}
`
``
160
`+
}
`
``
161
`+
self.map.insert(id, effective_vis);
`
``
162
`+
}
`
``
163
`+
}
`
``
164
+
``
165
`+
impl<Id: Hash + Eq + Copy + Into> AccessLevels {
`
``
166
`` +
// parent_id
is not necessarily a parent in source code tree,
``
``
167
`+
// it is the node from which the maximum effective visibility is inherited.
`
``
168
`+
pub fn update(
`
``
169
`+
&mut self,
`
``
170
`+
id: Id,
`
``
171
`+
nominal_vis: Visibility,
`
``
172
`+
default_vis: impl FnOnce() -> Visibility,
`
``
173
`+
parent_id: Id,
`
``
174
`+
tag: AccessLevel,
`
``
175
`+
tree: impl DefIdTree,
`
``
176
`+
) -> Result<bool, ()> {
`
``
177
`+
let mut changed = false;
`
``
178
`+
let mut current_effective_vis = self
`
``
179
`+
.get_effective_vis(id)
`
``
180
`+
.copied()
`
``
181
`+
.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
`
``
182
`+
if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) {
`
``
183
`+
for level in AccessLevel::all_levels() {
`
``
184
`+
if tag >= level {
`
``
185
`+
let inherited_effective_vis_at_level = *inherited_effective_vis.get(level);
`
``
186
`+
let calculated_effective_vis =
`
``
187
`+
if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
`
``
188
`+
inherited_effective_vis_at_level
`
``
189
`+
} else {
`
``
190
`+
nominal_vis
`
``
191
`+
};
`
``
192
`+
changed |= current_effective_vis.update(calculated_effective_vis, level, tree);
`
``
193
`+
}
`
``
194
`+
}
`
``
195
`+
} else {
`
``
196
`+
if !id.into().is_crate_root() {
`
``
197
`+
return Err(());
`
``
198
`+
}
`
``
199
`+
changed |= current_effective_vis.update(Visibility::Public, AccessLevel::Public, tree);
`
``
200
`+
}
`
``
201
`+
self.map.insert(id, current_effective_vis);
`
``
202
`+
Ok(changed)
`
``
203
`+
}
`
132
204
`}
`
133
205
``
134
206
`impl Default for AccessLevels {
`