22
33use std:: iter;
44
5+ use base_db:: Crate ;
56use hir_expand:: { InFile , Lookup } ;
67use la_arena:: ArenaMap ;
78use syntax:: ast:: { self , HasVisibility } ;
@@ -19,6 +20,8 @@ pub use crate::item_tree::{RawVisibility, VisibilityExplicitness};
1920pub enum Visibility {
2021 /// Visibility is restricted to a certain module.
2122 Module ( ModuleId , VisibilityExplicitness ) ,
23+ /// Visibility is restricted to the crate.
24+ PubCrate ( Crate ) ,
2225 /// Visibility is unrestricted.
2326 Public ,
2427}
@@ -41,6 +44,7 @@ impl Visibility {
4144 pub fn is_visible_from ( self , db : & dyn DefDatabase , from_module : ModuleId ) -> bool {
4245 let to_module = match self {
4346 Visibility :: Module ( m, _) => m,
47+ Visibility :: PubCrate ( krate) => return from_module. krate == krate,
4448 Visibility :: Public => return true ,
4549 } ;
4650 // if they're not in the same crate, it can't be visible
@@ -59,6 +63,7 @@ impl Visibility {
5963 ) -> bool {
6064 let to_module = match self {
6165 Visibility :: Module ( m, _) => m,
66+ Visibility :: PubCrate ( krate) => return def_map. krate ( ) == krate,
6267 Visibility :: Public => return true ,
6368 } ;
6469 // if they're not in the same crate, it can't be visible
@@ -132,26 +137,41 @@ impl Visibility {
132137 pub ( crate ) fn max ( self , other : Visibility , def_map : & DefMap ) -> Option < Visibility > {
133138 match ( self , other) {
134139 ( _, Visibility :: Public ) | ( Visibility :: Public , _) => Some ( Visibility :: Public ) ,
140+ ( Visibility :: PubCrate ( krate) , Visibility :: PubCrate ( krateb) ) => {
141+ if krate == krateb {
142+ Some ( Visibility :: PubCrate ( krate) )
143+ } else {
144+ None
145+ }
146+ }
147+ ( Visibility :: Module ( mod_, _) , Visibility :: PubCrate ( krate) )
148+ | ( Visibility :: PubCrate ( krate) , Visibility :: Module ( mod_, _) ) => {
149+ if mod_. krate == krate {
150+ Some ( Visibility :: PubCrate ( krate) )
151+ } else {
152+ None
153+ }
154+ }
135155 ( Visibility :: Module ( mod_a, expl_a) , Visibility :: Module ( mod_b, expl_b) ) => {
136- if mod_a. krate != mod_b. krate {
156+ if mod_a. krate != def_map . krate ( ) || mod_b. krate != def_map . krate ( ) {
137157 return None ;
138158 }
139159
140160 let def_block = def_map. block_id ( ) ;
141- if ( mod_a. containing_block ( ) , mod_b. containing_block ( ) ) != ( def_block, def_block ) {
161+ if mod_a. containing_block ( ) != def_block || mod_b. containing_block ( ) != def_block {
142162 return None ;
143163 }
144164
145165 let mut a_ancestors =
146166 iter:: successors ( Some ( mod_a. local_id ) , |& m| def_map[ m] . parent ) ;
147- let mut b_ancestors =
148- iter:: successors ( Some ( mod_b. local_id ) , |& m| def_map[ m] . parent ) ;
149167
150168 if a_ancestors. any ( |m| m == mod_b. local_id ) {
151169 // B is above A
152170 return Some ( Visibility :: Module ( mod_b, expl_b) ) ;
153171 }
154172
173+ let mut b_ancestors =
174+ iter:: successors ( Some ( mod_b. local_id ) , |& m| def_map[ m] . parent ) ;
155175 if b_ancestors. any ( |m| m == mod_a. local_id ) {
156176 // A is above B
157177 return Some ( Visibility :: Module ( mod_a, expl_a) ) ;
@@ -169,26 +189,37 @@ impl Visibility {
169189 pub ( crate ) fn min ( self , other : Visibility , def_map : & DefMap ) -> Option < Visibility > {
170190 match ( self , other) {
171191 ( vis, Visibility :: Public ) | ( Visibility :: Public , vis) => Some ( vis) ,
192+ ( Visibility :: PubCrate ( krate) , Visibility :: PubCrate ( krateb) ) => {
193+ if krate == krateb {
194+ Some ( Visibility :: PubCrate ( krate) )
195+ } else {
196+ None
197+ }
198+ }
199+ ( Visibility :: Module ( mod_, exp) , Visibility :: PubCrate ( krate) )
200+ | ( Visibility :: PubCrate ( krate) , Visibility :: Module ( mod_, exp) ) => {
201+ if mod_. krate == krate { Some ( Visibility :: Module ( mod_, exp) ) } else { None }
202+ }
172203 ( Visibility :: Module ( mod_a, expl_a) , Visibility :: Module ( mod_b, expl_b) ) => {
173- if mod_a. krate != mod_b. krate {
204+ if mod_a. krate != def_map . krate ( ) || mod_b. krate != def_map . krate ( ) {
174205 return None ;
175206 }
176207
177208 let def_block = def_map. block_id ( ) ;
178- if ( mod_a. containing_block ( ) , mod_b. containing_block ( ) ) != ( def_block, def_block ) {
209+ if mod_a. containing_block ( ) != def_block || mod_b. containing_block ( ) != def_block {
179210 return None ;
180211 }
181212
182213 let mut a_ancestors =
183214 iter:: successors ( Some ( mod_a. local_id ) , |& m| def_map[ m] . parent ) ;
184- let mut b_ancestors =
185- iter:: successors ( Some ( mod_b. local_id ) , |& m| def_map[ m] . parent ) ;
186215
187216 if a_ancestors. any ( |m| m == mod_b. local_id ) {
188217 // B is above A
189218 return Some ( Visibility :: Module ( mod_a, expl_a) ) ;
190219 }
191220
221+ let mut b_ancestors =
222+ iter:: successors ( Some ( mod_b. local_id ) , |& m| def_map[ m] . parent ) ;
192223 if b_ancestors. any ( |m| m == mod_a. local_id ) {
193224 // A is above B
194225 return Some ( Visibility :: Module ( mod_b, expl_b) ) ;
0 commit comments