@@ -37,10 +37,14 @@ impl RawVisibility {
37
37
db : & dyn DefDatabase ,
38
38
node : InFile < Option < ast:: Visibility > > ,
39
39
) -> RawVisibility {
40
+ let node = match node. transpose ( ) {
41
+ None => return RawVisibility :: private ( ) ,
42
+ Some ( node) => node,
43
+ } ;
40
44
Self :: from_ast_with_span_map ( db, node. value , db. span_map ( node. file_id ) . as_ref ( ) )
41
45
}
42
46
43
- pub ( crate ) fn from_ast_with_span_map (
47
+ pub ( crate ) fn from_opt_ast_with_span_map (
44
48
db : & dyn DefDatabase ,
45
49
node : Option < ast:: Visibility > ,
46
50
span_map : SpanMapRef < ' _ > ,
@@ -49,29 +53,28 @@ impl RawVisibility {
49
53
None => return RawVisibility :: private ( ) ,
50
54
Some ( node) => node,
51
55
} ;
52
- match node. kind ( ) {
56
+ Self :: from_ast_with_span_map ( db, node, span_map)
57
+ }
58
+
59
+ fn from_ast_with_span_map (
60
+ db : & dyn DefDatabase ,
61
+ node : ast:: Visibility ,
62
+ span_map : SpanMapRef < ' _ > ,
63
+ ) -> RawVisibility {
64
+ let path = match node. kind ( ) {
53
65
ast:: VisibilityKind :: In ( path) => {
54
66
let path = ModPath :: from_src ( db. upcast ( ) , path, span_map) ;
55
- let path = match path {
67
+ match path {
56
68
None => return RawVisibility :: private ( ) ,
57
69
Some ( path) => path,
58
- } ;
59
- RawVisibility :: Module ( path, VisibilityExplicitness :: Explicit )
60
- }
61
- ast:: VisibilityKind :: PubCrate => {
62
- let path = ModPath :: from_kind ( PathKind :: Crate ) ;
63
- RawVisibility :: Module ( path, VisibilityExplicitness :: Explicit )
64
- }
65
- ast:: VisibilityKind :: PubSuper => {
66
- let path = ModPath :: from_kind ( PathKind :: Super ( 1 ) ) ;
67
- RawVisibility :: Module ( path, VisibilityExplicitness :: Explicit )
68
- }
69
- ast:: VisibilityKind :: PubSelf => {
70
- let path = ModPath :: from_kind ( PathKind :: Super ( 0 ) ) ;
71
- RawVisibility :: Module ( path, VisibilityExplicitness :: Explicit )
70
+ }
72
71
}
73
- ast:: VisibilityKind :: Pub => RawVisibility :: Public ,
74
- }
72
+ ast:: VisibilityKind :: PubCrate => ModPath :: from_kind ( PathKind :: Crate ) ,
73
+ ast:: VisibilityKind :: PubSuper => ModPath :: from_kind ( PathKind :: Super ( 1 ) ) ,
74
+ ast:: VisibilityKind :: PubSelf => ModPath :: from_kind ( PathKind :: Super ( 0 ) ) ,
75
+ ast:: VisibilityKind :: Pub => return RawVisibility :: Public ,
76
+ } ;
77
+ RawVisibility :: Module ( path, VisibilityExplicitness :: Explicit )
75
78
}
76
79
77
80
pub fn resolve (
@@ -94,6 +97,10 @@ pub enum Visibility {
94
97
}
95
98
96
99
impl Visibility {
100
+ pub ( crate ) fn is_visible_from_other_crate ( self ) -> bool {
101
+ matches ! ( self , Visibility :: Public )
102
+ }
103
+
97
104
#[ tracing:: instrument( skip_all) ]
98
105
pub fn is_visible_from ( self , db : & dyn DefDatabase , from_module : ModuleId ) -> bool {
99
106
let to_module = match self {
@@ -105,45 +112,59 @@ impl Visibility {
105
112
return false ;
106
113
}
107
114
let def_map = from_module. def_map ( db) ;
108
- self . is_visible_from_def_map ( db, & def_map, from_module. local_id )
109
- }
110
-
111
- pub ( crate ) fn is_visible_from_other_crate ( self ) -> bool {
112
- matches ! ( self , Visibility :: Public )
115
+ Self :: is_visible_from_def_map_ ( db, & def_map, to_module, from_module. local_id )
113
116
}
114
117
115
118
pub ( crate ) fn is_visible_from_def_map (
116
119
self ,
117
120
db : & dyn DefDatabase ,
118
121
def_map : & DefMap ,
119
- mut from_module : LocalModuleId ,
122
+ from_module : LocalModuleId ,
120
123
) -> bool {
121
- let mut to_module = match self {
124
+ let to_module = match self {
122
125
Visibility :: Module ( m, _) => m,
123
126
Visibility :: Public => return true ,
124
127
} ;
128
+ // if they're not in the same crate, it can't be visible
129
+ if def_map. krate ( ) != to_module. krate {
130
+ return false ;
131
+ }
132
+ Self :: is_visible_from_def_map_ ( db, def_map, to_module, from_module)
133
+ }
125
134
135
+ fn is_visible_from_def_map_ (
136
+ db : & dyn DefDatabase ,
137
+ def_map : & DefMap ,
138
+ mut to_module : ModuleId ,
139
+ mut from_module : LocalModuleId ,
140
+ ) -> bool {
141
+ debug_assert_eq ! ( to_module. krate, def_map. krate( ) ) ;
126
142
// `to_module` might be the root module of a block expression. Those have the same
127
143
// visibility as the containing module (even though no items are directly nameable from
128
144
// there, getting this right is important for method resolution).
129
145
// In that case, we adjust the visibility of `to_module` to point to the containing module.
130
146
131
147
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
132
148
// currently computing, so we must not call the `def_map` query for it.
133
- let mut arc ;
149
+ let def_map_block = def_map . block_id ( ) ;
134
150
loop {
135
- let to_module_def_map =
136
- if to_module. krate == def_map. krate ( ) && to_module. block == def_map. block_id ( ) {
151
+ match ( to_module. block , def_map_block) {
152
+ // to_module is not a block, so there is no parent def map to use
153
+ ( None , _) => ( ) ,
154
+ ( Some ( a) , Some ( b) ) if a == b => {
137
155
cov_mark:: hit!( is_visible_from_same_block_def_map) ;
138
- def_map
139
- } else {
140
- arc = to_module. def_map ( db) ;
141
- & arc
142
- } ;
143
- match to_module_def_map. parent ( ) {
144
- Some ( parent) => to_module = parent,
145
- None => break ,
156
+ if let Some ( parent) = def_map. parent ( ) {
157
+ to_module = parent;
158
+ }
159
+ }
160
+ _ => {
161
+ if let Some ( parent) = to_module. def_map ( db) . parent ( ) {
162
+ to_module = parent;
163
+ continue ;
164
+ }
165
+ }
146
166
}
167
+ break ;
147
168
}
148
169
149
170
// from_module needs to be a descendant of to_module
@@ -176,30 +197,25 @@ impl Visibility {
176
197
/// visible in unrelated modules).
177
198
pub ( crate ) fn max ( self , other : Visibility , def_map : & DefMap ) -> Option < Visibility > {
178
199
match ( self , other) {
179
- ( Visibility :: Module ( _, _) | Visibility :: Public , Visibility :: Public )
180
- | ( Visibility :: Public , Visibility :: Module ( _, _) ) => Some ( Visibility :: Public ) ,
181
- ( Visibility :: Module ( mod_a, vis_a) , Visibility :: Module ( mod_b, vis_b) ) => {
200
+ ( _, Visibility :: Public ) | ( Visibility :: Public , _) => Some ( Visibility :: Public ) ,
201
+ ( Visibility :: Module ( mod_a, expl_a) , Visibility :: Module ( mod_b, expl_b) ) => {
182
202
if mod_a. krate != mod_b. krate {
183
203
return None ;
184
204
}
185
205
186
- let mut a_ancestors = iter:: successors ( Some ( mod_a. local_id ) , |& m| {
187
- let parent_id = def_map[ m] . parent ?;
188
- Some ( parent_id)
189
- } ) ;
190
- let mut b_ancestors = iter:: successors ( Some ( mod_b. local_id ) , |& m| {
191
- let parent_id = def_map[ m] . parent ?;
192
- Some ( parent_id)
193
- } ) ;
206
+ let mut a_ancestors =
207
+ iter:: successors ( Some ( mod_a. local_id ) , |& m| def_map[ m] . parent ) ;
208
+ let mut b_ancestors =
209
+ iter:: successors ( Some ( mod_b. local_id ) , |& m| def_map[ m] . parent ) ;
194
210
195
211
if a_ancestors. any ( |m| m == mod_b. local_id ) {
196
212
// B is above A
197
- return Some ( Visibility :: Module ( mod_b, vis_b ) ) ;
213
+ return Some ( Visibility :: Module ( mod_b, expl_b ) ) ;
198
214
}
199
215
200
216
if b_ancestors. any ( |m| m == mod_a. local_id ) {
201
217
// A is above B
202
- return Some ( Visibility :: Module ( mod_a, vis_a ) ) ;
218
+ return Some ( Visibility :: Module ( mod_a, expl_a ) ) ;
203
219
}
204
220
205
221
None
@@ -208,7 +224,8 @@ impl Visibility {
208
224
}
209
225
}
210
226
211
- /// Whether the item was imported through `pub(crate) use` or just `use`.
227
+ /// Whether the item was imported through an explicit `pub(crate) use` or just a `use` without
228
+ /// visibility.
212
229
#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
213
230
pub enum VisibilityExplicitness {
214
231
Explicit ,
0 commit comments