@@ -263,7 +263,7 @@ use self::symbol_state::{
263263 LiveBindingsIterator , LiveDeclaration , LiveDeclarationsIterator , ScopedDefinitionId ,
264264 SymbolBindings , SymbolDeclarations , SymbolState ,
265265} ;
266- use crate :: semantic_index:: ast_ids:: ScopedUseId ;
266+ use crate :: semantic_index:: ast_ids:: { ScopedExpressionId , ScopedUseId } ;
267267use crate :: semantic_index:: definition:: Definition ;
268268use crate :: semantic_index:: narrowing_constraints:: {
269269 NarrowingConstraints , NarrowingConstraintsBuilder , NarrowingConstraintsIterator ,
@@ -298,7 +298,7 @@ pub(crate) struct UseDefMap<'db> {
298298 bindings_by_use : IndexVec < ScopedUseId , SymbolBindings > ,
299299
300300 /// Tracks whether or not a given use of a symbol is reachable from the start of the scope.
301- reachability_by_use : IndexVec < ScopedUseId , ScopedVisibilityConstraintId > ,
301+ expression_reachability : FxHashMap < ScopedExpressionId , ScopedVisibilityConstraintId > ,
302302
303303 /// If the definition is a binding (only) -- `x = 1` for example -- then we need
304304 /// [`SymbolDeclarations`] to know whether this binding is permitted by the live declarations.
@@ -359,8 +359,23 @@ impl<'db> UseDefMap<'db> {
359359 . is_always_false ( )
360360 }
361361
362- pub ( super ) fn is_symbol_use_reachable ( & self , db : & dyn crate :: Db , use_id : ScopedUseId ) -> bool {
363- self . is_reachable ( db, self . reachability_by_use [ use_id] )
362+ #[ track_caller]
363+ pub ( super ) fn is_expression_reachable (
364+ & self ,
365+ db : & dyn crate :: Db ,
366+ expression_id : ScopedExpressionId ,
367+ ) -> bool {
368+ !self
369+ . visibility_constraints
370+ . evaluate (
371+ db,
372+ & self . predicates ,
373+ * self
374+ . expression_reachability
375+ . get ( & expression_id)
376+ . expect ( "only called on expressions with recorded reachability" ) ,
377+ )
378+ . is_always_false ( )
364379 }
365380
366381 pub ( crate ) fn public_bindings (
@@ -618,7 +633,7 @@ pub(super) struct UseDefMapBuilder<'db> {
618633 pub ( super ) reachability : ScopedVisibilityConstraintId ,
619634
620635 /// Tracks whether or not a given use of a symbol is reachable from the start of the scope.
621- reachability_by_use : IndexVec < ScopedUseId , ScopedVisibilityConstraintId > ,
636+ expression_reachability : FxHashMap < ScopedExpressionId , ScopedVisibilityConstraintId > ,
622637
623638 /// Live declarations for each so-far-recorded binding.
624639 declarations_by_binding : FxHashMap < Definition < ' db > , SymbolDeclarations > ,
@@ -644,7 +659,7 @@ impl Default for UseDefMapBuilder<'_> {
644659 scope_start_visibility : ScopedVisibilityConstraintId :: ALWAYS_TRUE ,
645660 bindings_by_use : IndexVec :: new ( ) ,
646661 reachability : ScopedVisibilityConstraintId :: ALWAYS_TRUE ,
647- reachability_by_use : IndexVec :: new ( ) ,
662+ expression_reachability : FxHashMap :: default ( ) ,
648663 declarations_by_binding : FxHashMap :: default ( ) ,
649664 bindings_by_declaration : FxHashMap :: default ( ) ,
650665 symbol_states : IndexVec :: new ( ) ,
@@ -799,16 +814,25 @@ impl<'db> UseDefMapBuilder<'db> {
799814 symbol_state. record_binding ( def_id, self . scope_start_visibility ) ;
800815 }
801816
802- pub ( super ) fn record_use ( & mut self , symbol : ScopedSymbolId , use_id : ScopedUseId ) {
817+ pub ( super ) fn record_use (
818+ & mut self ,
819+ symbol : ScopedSymbolId ,
820+ use_id : ScopedUseId ,
821+ expression_id : ScopedExpressionId ,
822+ ) {
803823 // We have a use of a symbol; clone the current bindings for that symbol, and record them
804824 // as the live bindings for this use.
805825 let new_use = self
806826 . bindings_by_use
807827 . push ( self . symbol_states [ symbol] . bindings ( ) . clone ( ) ) ;
808828 debug_assert_eq ! ( use_id, new_use) ;
809829
810- let new_use = self . reachability_by_use . push ( self . reachability ) ;
811- debug_assert_eq ! ( use_id, new_use) ;
830+ self . record_expression_reachability ( expression_id) ;
831+ }
832+
833+ pub ( super ) fn record_expression_reachability ( & mut self , expression_id : ScopedExpressionId ) {
834+ self . expression_reachability
835+ . insert ( expression_id, self . reachability ) ;
812836 }
813837
814838 pub ( super ) fn snapshot_eager_bindings (
@@ -905,7 +929,6 @@ impl<'db> UseDefMapBuilder<'db> {
905929 self . all_definitions . shrink_to_fit ( ) ;
906930 self . symbol_states . shrink_to_fit ( ) ;
907931 self . bindings_by_use . shrink_to_fit ( ) ;
908- self . reachability_by_use . shrink_to_fit ( ) ;
909932 self . declarations_by_binding . shrink_to_fit ( ) ;
910933 self . bindings_by_declaration . shrink_to_fit ( ) ;
911934 self . eager_bindings . shrink_to_fit ( ) ;
@@ -916,7 +939,7 @@ impl<'db> UseDefMapBuilder<'db> {
916939 narrowing_constraints : self . narrowing_constraints . build ( ) ,
917940 visibility_constraints : self . visibility_constraints . build ( ) ,
918941 bindings_by_use : self . bindings_by_use ,
919- reachability_by_use : self . reachability_by_use ,
942+ expression_reachability : self . expression_reachability ,
920943 public_symbols : self . symbol_states ,
921944 declarations_by_binding : self . declarations_by_binding ,
922945 bindings_by_declaration : self . bindings_by_declaration ,
0 commit comments