@@ -263,7 +263,7 @@ use self::symbol_state::{
263
263
LiveBindingsIterator , LiveDeclaration , LiveDeclarationsIterator , ScopedDefinitionId ,
264
264
SymbolBindings , SymbolDeclarations , SymbolState ,
265
265
} ;
266
- use crate :: semantic_index:: ast_ids:: ScopedUseId ;
266
+ use crate :: semantic_index:: ast_ids:: { ScopedExpressionId , ScopedUseId } ;
267
267
use crate :: semantic_index:: definition:: Definition ;
268
268
use crate :: semantic_index:: narrowing_constraints:: {
269
269
NarrowingConstraints , NarrowingConstraintsBuilder , NarrowingConstraintsIterator ,
@@ -297,8 +297,8 @@ pub(crate) struct UseDefMap<'db> {
297
297
/// [`SymbolBindings`] reaching a [`ScopedUseId`].
298
298
bindings_by_use : IndexVec < ScopedUseId , SymbolBindings > ,
299
299
300
- /// 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 > ,
300
+ /// Tracks whether or not a given expression is reachable from the start of the scope.
301
+ expression_reachability : FxHashMap < ScopedExpressionId , ScopedVisibilityConstraintId > ,
302
302
303
303
/// If the definition is a binding (only) -- `x = 1` for example -- then we need
304
304
/// [`SymbolDeclarations`] to know whether this binding is permitted by the live declarations.
@@ -359,8 +359,27 @@ impl<'db> UseDefMap<'db> {
359
359
. is_always_false ( )
360
360
}
361
361
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
+ /// Check whether or not a given expression is reachable from the start of the scope. This
363
+ /// is a local analysis which does not capture the possibility that the entire scope might
364
+ /// be unreachable. Use [`super::SemanticIndex::is_expression_reachable`] for the global
365
+ /// analysis.
366
+ #[ track_caller]
367
+ pub ( super ) fn is_expression_reachable (
368
+ & self ,
369
+ db : & dyn crate :: Db ,
370
+ expression_id : ScopedExpressionId ,
371
+ ) -> bool {
372
+ !self
373
+ . visibility_constraints
374
+ . evaluate (
375
+ db,
376
+ & self . predicates ,
377
+ * self
378
+ . expression_reachability
379
+ . get ( & expression_id)
380
+ . expect ( "`is_expression_reachable` should only be called on expressions with recorded reachability" ) ,
381
+ )
382
+ . is_always_false ( )
364
383
}
365
384
366
385
pub ( crate ) fn public_bindings (
@@ -617,8 +636,8 @@ pub(super) struct UseDefMapBuilder<'db> {
617
636
/// The use of `x` is recorded with a reachability constraint of `[test]`.
618
637
pub ( super ) reachability : ScopedVisibilityConstraintId ,
619
638
620
- /// 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 > ,
639
+ /// Tracks whether or not a given expression is reachable from the start of the scope.
640
+ expression_reachability : FxHashMap < ScopedExpressionId , ScopedVisibilityConstraintId > ,
622
641
623
642
/// Live declarations for each so-far-recorded binding.
624
643
declarations_by_binding : FxHashMap < Definition < ' db > , SymbolDeclarations > ,
@@ -644,7 +663,7 @@ impl Default for UseDefMapBuilder<'_> {
644
663
scope_start_visibility : ScopedVisibilityConstraintId :: ALWAYS_TRUE ,
645
664
bindings_by_use : IndexVec :: new ( ) ,
646
665
reachability : ScopedVisibilityConstraintId :: ALWAYS_TRUE ,
647
- reachability_by_use : IndexVec :: new ( ) ,
666
+ expression_reachability : FxHashMap :: default ( ) ,
648
667
declarations_by_binding : FxHashMap :: default ( ) ,
649
668
bindings_by_declaration : FxHashMap :: default ( ) ,
650
669
symbol_states : IndexVec :: new ( ) ,
@@ -799,16 +818,27 @@ impl<'db> UseDefMapBuilder<'db> {
799
818
symbol_state. record_binding ( def_id, self . scope_start_visibility ) ;
800
819
}
801
820
802
- pub ( super ) fn record_use ( & mut self , symbol : ScopedSymbolId , use_id : ScopedUseId ) {
821
+ pub ( super ) fn record_use (
822
+ & mut self ,
823
+ symbol : ScopedSymbolId ,
824
+ use_id : ScopedUseId ,
825
+ expression_id : ScopedExpressionId ,
826
+ ) {
803
827
// We have a use of a symbol; clone the current bindings for that symbol, and record them
804
828
// as the live bindings for this use.
805
829
let new_use = self
806
830
. bindings_by_use
807
831
. push ( self . symbol_states [ symbol] . bindings ( ) . clone ( ) ) ;
808
832
debug_assert_eq ! ( use_id, new_use) ;
809
833
810
- let new_use = self . reachability_by_use . push ( self . reachability ) ;
811
- debug_assert_eq ! ( use_id, new_use) ;
834
+ // Track reachability of all uses of symbols to silence `unresolved-reference`
835
+ // diagnostics in unreachable code.
836
+ self . record_expression_reachability ( expression_id) ;
837
+ }
838
+
839
+ pub ( super ) fn record_expression_reachability ( & mut self , expression_id : ScopedExpressionId ) {
840
+ self . expression_reachability
841
+ . insert ( expression_id, self . reachability ) ;
812
842
}
813
843
814
844
pub ( super ) fn snapshot_eager_bindings (
@@ -905,7 +935,7 @@ impl<'db> UseDefMapBuilder<'db> {
905
935
self . all_definitions . shrink_to_fit ( ) ;
906
936
self . symbol_states . shrink_to_fit ( ) ;
907
937
self . bindings_by_use . shrink_to_fit ( ) ;
908
- self . reachability_by_use . shrink_to_fit ( ) ;
938
+ self . expression_reachability . shrink_to_fit ( ) ;
909
939
self . declarations_by_binding . shrink_to_fit ( ) ;
910
940
self . bindings_by_declaration . shrink_to_fit ( ) ;
911
941
self . eager_bindings . shrink_to_fit ( ) ;
@@ -916,7 +946,7 @@ impl<'db> UseDefMapBuilder<'db> {
916
946
narrowing_constraints : self . narrowing_constraints . build ( ) ,
917
947
visibility_constraints : self . visibility_constraints . build ( ) ,
918
948
bindings_by_use : self . bindings_by_use ,
919
- reachability_by_use : self . reachability_by_use ,
949
+ expression_reachability : self . expression_reachability ,
920
950
public_symbols : self . symbol_states ,
921
951
declarations_by_binding : self . declarations_by_binding ,
922
952
bindings_by_declaration : self . bindings_by_declaration ,
0 commit comments