244244use ruff_index:: { IndexVec , newtype_index} ;
245245use ruff_text_size:: TextRange ;
246246use rustc_hash:: { FxBuildHasher , FxHashMap } ;
247+ use thin_vec:: ThinVec ;
247248
248249use crate :: ast_ids:: ScopedUseId ;
249250use crate :: definition:: { Definition , DefinitionState } ;
@@ -327,7 +328,7 @@ pub struct UseDefMap<'db> {
327328 ///
328329 /// This is only used for kwargs expressions, whose corresponding `bindings_by_use` entry
329330 /// is empty.
330- multi_bindings_by_use : FxHashMap < ScopedUseId , Vec < Bindings > > ,
331+ multi_bindings_by_use : MultiBindingsByUse ,
331332
332333 /// Tracks the reachability constraint for statements and certain sub-expressions
333334 /// (e.g. ternary branches, boolean operator operands), keyed by their text range.
@@ -397,6 +398,27 @@ struct RangeInfo {
397398 in_type_checking_block : bool ,
398399}
399400
401+ #[ derive( Debug , PartialEq , Eq , salsa:: Update , get_size2:: GetSize ) ]
402+ struct MultiBindingsByUse ( ThinVec < ( ScopedUseId , Box < [ Bindings ] > ) > ) ;
403+
404+ impl MultiBindingsByUse {
405+ fn from_map ( map : FxHashMap < ScopedUseId , Vec < Bindings > > ) -> Self {
406+ let mut entries = map
407+ . into_iter ( )
408+ . map ( |( use_id, bindings) | ( use_id, bindings. into_boxed_slice ( ) ) )
409+ . collect :: < Vec < _ > > ( ) ;
410+ entries. sort_unstable_by_key ( |( use_id, _) | use_id. as_u32 ( ) ) ;
411+ Self ( entries. into_iter ( ) . collect ( ) )
412+ }
413+
414+ fn get ( & self , use_id : ScopedUseId ) -> Option < & [ Bindings ] > {
415+ self . 0
416+ . binary_search_by_key ( & use_id. as_u32 ( ) , |( candidate, _) | candidate. as_u32 ( ) )
417+ . ok ( )
418+ . map ( |index| self . 0 [ index] . 1 . as_ref ( ) )
419+ }
420+ }
421+
400422pub enum ApplicableConstraints < ' map , ' db > {
401423 UnboundBinding ( NarrowingEvaluator < ' map , ' db > ) ,
402424 ConstrainedBindings ( BindingWithConstraintsIterator < ' map , ' db > ) ,
@@ -444,7 +466,7 @@ impl<'db> UseDefMap<'db> {
444466 use_id : ScopedUseId ,
445467 ) -> impl Iterator < Item = BindingWithConstraintsIterator < ' _ , ' db > > {
446468 self . multi_bindings_by_use
447- . get ( & use_id)
469+ . get ( use_id)
448470 . map ( |member_bindings| {
449471 member_bindings. iter ( ) . map ( |bindings| {
450472 self . bindings_iterator ( bindings, BoundnessAnalysis :: BasedOnUnboundVisibility )
@@ -1764,6 +1786,7 @@ impl<'db> UseDefMapBuilder<'db> {
17641786 }
17651787 }
17661788 self . reachability_constraints . mark_used ( self . reachability ) ;
1789+ let multi_bindings_by_use = MultiBindingsByUse :: from_map ( self . multi_bindings_by_use ) ;
17671790
17681791 UseDefMap {
17691792 all_definitions : self . all_definitions ,
@@ -1773,7 +1796,7 @@ impl<'db> UseDefMapBuilder<'db> {
17731796 interned_bindings,
17741797 interned_declarations,
17751798 bindings_by_use,
1776- multi_bindings_by_use : self . multi_bindings_by_use ,
1799+ multi_bindings_by_use,
17771800 range_reachability : self . range_reachability ,
17781801 end_of_scope_symbols : self . symbol_states ,
17791802 end_of_scope_members,
0 commit comments