@@ -37,10 +37,14 @@ impl RawVisibility {
3737 db : & dyn DefDatabase ,
3838 node : InFile < Option < ast:: Visibility > > ,
3939 ) -> RawVisibility {
40+ let node = match node. transpose ( ) {
41+ None => return RawVisibility :: private ( ) ,
42+ Some ( node) => node,
43+ } ;
4044 Self :: from_ast_with_span_map ( db, node. value , db. span_map ( node. file_id ) . as_ref ( ) )
4145 }
4246
43- pub ( crate ) fn from_ast_with_span_map (
47+ pub ( crate ) fn from_opt_ast_with_span_map (
4448 db : & dyn DefDatabase ,
4549 node : Option < ast:: Visibility > ,
4650 span_map : SpanMapRef < ' _ > ,
@@ -49,29 +53,28 @@ impl RawVisibility {
4953 None => return RawVisibility :: private ( ) ,
5054 Some ( node) => node,
5155 } ;
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 ( ) {
5365 ast:: VisibilityKind :: In ( path) => {
5466 let path = ModPath :: from_src ( db. upcast ( ) , path, span_map) ;
55- let path = match path {
67+ match path {
5668 None => return RawVisibility :: private ( ) ,
5769 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+ }
7271 }
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 )
7578 }
7679
7780 pub fn resolve (
@@ -94,6 +97,10 @@ pub enum Visibility {
9497}
9598
9699impl Visibility {
100+ pub ( crate ) fn is_visible_from_other_crate ( self ) -> bool {
101+ matches ! ( self , Visibility :: Public )
102+ }
103+
97104 #[ tracing:: instrument( skip_all) ]
98105 pub fn is_visible_from ( self , db : & dyn DefDatabase , from_module : ModuleId ) -> bool {
99106 let to_module = match self {
@@ -105,45 +112,59 @@ impl Visibility {
105112 return false ;
106113 }
107114 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 )
113116 }
114117
115118 pub ( crate ) fn is_visible_from_def_map (
116119 self ,
117120 db : & dyn DefDatabase ,
118121 def_map : & DefMap ,
119- mut from_module : LocalModuleId ,
122+ from_module : LocalModuleId ,
120123 ) -> bool {
121- let mut to_module = match self {
124+ let to_module = match self {
122125 Visibility :: Module ( m, _) => m,
123126 Visibility :: Public => return true ,
124127 } ;
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+ }
125134
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( ) ) ;
126142 // `to_module` might be the root module of a block expression. Those have the same
127143 // visibility as the containing module (even though no items are directly nameable from
128144 // there, getting this right is important for method resolution).
129145 // In that case, we adjust the visibility of `to_module` to point to the containing module.
130146
131147 // Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
132148 // 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 ( ) ;
134150 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 => {
137155 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+ }
146166 }
167+ break ;
147168 }
148169
149170 // from_module needs to be a descendant of to_module
@@ -176,30 +197,25 @@ impl Visibility {
176197 /// visible in unrelated modules).
177198 pub ( crate ) fn max ( self , other : Visibility , def_map : & DefMap ) -> Option < Visibility > {
178199 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) ) => {
182202 if mod_a. krate != mod_b. krate {
183203 return None ;
184204 }
185205
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 ) ;
194210
195211 if a_ancestors. any ( |m| m == mod_b. local_id ) {
196212 // B is above A
197- return Some ( Visibility :: Module ( mod_b, vis_b ) ) ;
213+ return Some ( Visibility :: Module ( mod_b, expl_b ) ) ;
198214 }
199215
200216 if b_ancestors. any ( |m| m == mod_a. local_id ) {
201217 // A is above B
202- return Some ( Visibility :: Module ( mod_a, vis_a ) ) ;
218+ return Some ( Visibility :: Module ( mod_a, expl_a ) ) ;
203219 }
204220
205221 None
@@ -208,7 +224,8 @@ impl Visibility {
208224 }
209225}
210226
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.
212229#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
213230pub enum VisibilityExplicitness {
214231 Explicit ,
0 commit comments