@@ -61,7 +61,7 @@ impl ModuleScope {
61
61
62
62
/// `Resolution` is basically `DefId` atm, but it should account for stuff like
63
63
/// multiple namespaces, ambiguity and errors.
64
- #[ derive( Debug , Clone , PartialEq , Eq ) ]
64
+ #[ derive( Debug , Clone , PartialEq , Eq , Default ) ]
65
65
pub struct Resolution {
66
66
/// None for unresolved
67
67
pub def : PerNs < ModuleDef > ,
@@ -154,6 +154,8 @@ struct Resolver<'a, DB> {
154
154
krate : Crate ,
155
155
module_tree : Arc < ModuleTree > ,
156
156
processed_imports : FxHashSet < ( ModuleId , ImportId ) > ,
157
+ /// If module `a` has `use b::*`, then this contains the mapping b -> a (and the import)
158
+ glob_imports : FxHashMap < ModuleId , Vec < ( ModuleId , ImportId ) > > ,
157
159
result : ItemMap ,
158
160
}
159
161
@@ -173,6 +175,7 @@ where
173
175
krate,
174
176
module_tree,
175
177
processed_imports : FxHashSet :: default ( ) ,
178
+ glob_imports : FxHashMap :: default ( ) ,
176
179
result : ItemMap :: default ( ) ,
177
180
}
178
181
}
@@ -281,12 +284,28 @@ where
281
284
// glob import from other crate => we can just import everything once
282
285
let item_map = self . db . item_map ( m. krate ) ;
283
286
let scope = & item_map[ m. module_id ] ;
284
- self . update ( module_id, |items| {
285
- // TODO: handle shadowing and visibility
286
- items. items . extend (
287
- scope. items . iter ( ) . map ( |( name, res) | ( name. clone ( ) , res. clone ( ) ) ) ,
288
- ) ;
289
- } ) ;
287
+ let items = scope
288
+ . items
289
+ . iter ( )
290
+ . map ( |( name, res) | ( name. clone ( ) , res. clone ( ) ) )
291
+ . collect :: < Vec < _ > > ( ) ;
292
+ self . update ( module_id, Some ( import_id) , & items) ;
293
+ } else {
294
+ // glob import from same crate => we do an initial
295
+ // import, and then need to propagate any further
296
+ // additions
297
+ let scope = & self . result [ m. module_id ] ;
298
+ let items = scope
299
+ . items
300
+ . iter ( )
301
+ . map ( |( name, res) | ( name. clone ( ) , res. clone ( ) ) )
302
+ . collect :: < Vec < _ > > ( ) ;
303
+ self . update ( module_id, Some ( import_id) , & items) ;
304
+ // record the glob import in case we add further items
305
+ self . glob_imports
306
+ . entry ( m. module_id )
307
+ . or_default ( )
308
+ . push ( ( module_id, import_id) ) ;
290
309
}
291
310
}
292
311
Some ( ModuleDef :: Enum ( e) ) => {
@@ -304,9 +323,7 @@ where
304
323
Some ( ( name, res) )
305
324
} )
306
325
. collect :: < Vec < _ > > ( ) ;
307
- self . update ( module_id, |items| {
308
- items. items . extend ( resolutions) ;
309
- } ) ;
326
+ self . update ( module_id, Some ( import_id) , & resolutions) ;
310
327
}
311
328
Some ( d) => {
312
329
log:: debug!( "glob import {:?} from non-module/enum {:?}" , import, d) ;
@@ -328,17 +345,61 @@ where
328
345
}
329
346
}
330
347
}
331
- self . update ( module_id, |items| {
332
- let res = Resolution { def, import : Some ( import_id) } ;
333
- items. items . insert ( name, res) ;
334
- } ) ;
348
+ let resolution = Resolution { def, import : Some ( import_id) } ;
349
+ self . update ( module_id, None , & [ ( name, resolution) ] ) ;
335
350
}
336
351
reached_fixedpoint
337
352
}
338
353
339
- fn update ( & mut self , module_id : ModuleId , f : impl FnOnce ( & mut ModuleScope ) ) {
354
+ fn update (
355
+ & mut self ,
356
+ module_id : ModuleId ,
357
+ import : Option < ImportId > ,
358
+ resolutions : & [ ( Name , Resolution ) ] ,
359
+ ) {
360
+ self . update_recursive ( module_id, import, resolutions, 0 )
361
+ }
362
+
363
+ fn update_recursive (
364
+ & mut self ,
365
+ module_id : ModuleId ,
366
+ import : Option < ImportId > ,
367
+ resolutions : & [ ( Name , Resolution ) ] ,
368
+ depth : usize ,
369
+ ) {
370
+ if depth > 100 {
371
+ // prevent stack overflows (but this shouldn't be possible)
372
+ panic ! ( "infinite recursion in glob imports!" ) ;
373
+ }
340
374
let module_items = self . result . per_module . get_mut ( module_id) . unwrap ( ) ;
341
- f ( module_items)
375
+ let mut changed = false ;
376
+ for ( name, res) in resolutions {
377
+ let existing = module_items. items . entry ( name. clone ( ) ) . or_default ( ) ;
378
+ if existing. def . types . is_none ( ) && res. def . types . is_some ( ) {
379
+ existing. def . types = res. def . types ;
380
+ existing. import = import. or ( res. import ) ;
381
+ changed = true ;
382
+ }
383
+ if existing. def . values . is_none ( ) && res. def . values . is_some ( ) {
384
+ existing. def . values = res. def . values ;
385
+ existing. import = import. or ( res. import ) ;
386
+ changed = true ;
387
+ }
388
+ }
389
+ if !changed {
390
+ return ;
391
+ }
392
+ let glob_imports = self
393
+ . glob_imports
394
+ . get ( & module_id)
395
+ . into_iter ( )
396
+ . flat_map ( |v| v. iter ( ) )
397
+ . cloned ( )
398
+ . collect :: < Vec < _ > > ( ) ;
399
+ for ( glob_importing_module, glob_import) in glob_imports {
400
+ // We pass the glob import so that the tracked import in those modules is that glob import
401
+ self . update_recursive ( glob_importing_module, Some ( glob_import) , resolutions, depth + 1 ) ;
402
+ }
342
403
}
343
404
}
344
405
0 commit comments