@@ -51,6 +51,7 @@ use crate::semantic_index::use_def::{
5151} ;
5252use crate :: semantic_index:: { ExpressionsScopeMap , SemanticIndex , VisibleAncestorsIter } ;
5353use crate :: semantic_model:: HasTrackedScope ;
54+ use crate :: types:: PossiblyNarrowedPlaces ;
5455use crate :: unpack:: { EvaluationMode , Unpack , UnpackKind , UnpackPosition , UnpackValue } ;
5556use crate :: { Db , Program } ;
5657
@@ -857,7 +858,7 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> {
857858
858859 /// Adds a new predicate to the list of all predicates, but does not record it. Returns the
859860 /// predicate ID for later recording using
860- /// [`SemanticIndexBuilder::record_narrowing_constraint_id `].
861+ /// [`SemanticIndexBuilder::record_narrowing_constraint_id_for_places `].
861862 fn add_predicate ( & mut self , predicate : PredicateOrLiteral < ' db > ) -> ScopedPredicateId {
862863 self . current_use_def_map_mut ( ) . add_predicate ( predicate)
863864 }
@@ -868,27 +869,70 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> {
868869 . add_predicate ( predicate. negated ( ) )
869870 }
870871
871- /// Records a previously added narrowing constraint by adding it to all live bindings.
872- fn record_narrowing_constraint_id ( & mut self , predicate : ScopedPredicateId ) {
872+ /// Records a previously added narrowing constraint by adding it to the live bindings
873+ /// of the specified places.
874+ fn record_narrowing_constraint_id_for_places (
875+ & mut self ,
876+ predicate : ScopedPredicateId ,
877+ places : & PossiblyNarrowedPlaces ,
878+ ) {
873879 self . current_use_def_map_mut ( )
874- . record_narrowing_constraint ( predicate) ;
880+ . record_narrowing_constraint_for_places ( predicate, places ) ;
875881 }
876882
877- /// Adds and records a narrowing constraint, i.e. adds it to all live bindings .
883+ /// Adds and records a narrowing constraint for only the places that could possibly be narrowed .
878884 fn record_narrowing_constraint ( & mut self , predicate : PredicateOrLiteral < ' db > ) {
885+ let possibly_narrowed = self . compute_possibly_narrowed_places ( & predicate) ;
879886 let use_def = self . current_use_def_map_mut ( ) ;
880887 let predicate_id = use_def. add_predicate ( predicate) ;
881- use_def. record_narrowing_constraint ( predicate_id) ;
888+ use_def. record_narrowing_constraint_for_places ( predicate_id, & possibly_narrowed ) ;
882889 }
883890
884- /// Negates the given predicate and then adds it as a narrowing constraint to all live
885- /// bindings.
891+ /// Computes the conservative set of places that could possibly be narrowed by a predicate.
892+ ///
893+ /// This uses the closure-based approach to avoid calling Salsa queries that depend on
894+ /// the semantic index (which is still being built).
895+ fn compute_possibly_narrowed_places (
896+ & self ,
897+ predicate : & PredicateOrLiteral < ' db > ,
898+ ) -> PossiblyNarrowedPlaces {
899+ use crate :: types:: PossiblyNarrowedPlacesBuilder ;
900+
901+ match predicate {
902+ PredicateOrLiteral :: Literal ( _) => PossiblyNarrowedPlaces :: default ( ) ,
903+ PredicateOrLiteral :: Predicate ( pred) => {
904+ let place_table = self . current_place_table ( ) ;
905+
906+ match pred. node {
907+ PredicateNode :: Expression ( expression) => {
908+ let module = self . module ;
909+ let expression_node = expression. node_ref ( self . db , module) ;
910+ PossiblyNarrowedPlacesBuilder :: new ( self . db , place_table)
911+ . expression ( expression_node)
912+ }
913+ PredicateNode :: Pattern ( pattern) => {
914+ let module = self . module ;
915+ PossiblyNarrowedPlacesBuilder :: new ( self . db , place_table)
916+ . pattern ( pattern, module)
917+ }
918+ PredicateNode :: ReturnsNever ( _) | PredicateNode :: StarImportPlaceholder ( _) => {
919+ // These predicates don't narrow any places
920+ PossiblyNarrowedPlaces :: default ( )
921+ }
922+ }
923+ }
924+ }
925+ }
926+
927+ /// Negates the given predicate and then adds it as a narrowing constraint to the places
928+ /// that could possibly be narrowed.
886929 fn record_negated_narrowing_constraint (
887930 & mut self ,
888931 predicate : PredicateOrLiteral < ' db > ,
889932 ) -> ScopedPredicateId {
933+ let possibly_narrowed = self . compute_possibly_narrowed_places ( & predicate) ;
890934 let id = self . add_negated_predicate ( predicate) ;
891- self . record_narrowing_constraint_id ( id) ;
935+ self . record_narrowing_constraint_id_for_places ( id, & possibly_narrowed ) ;
892936 id
893937 }
894938
@@ -2767,6 +2811,7 @@ impl<'ast> Visitor<'ast> for SemanticIndexBuilder<'_, 'ast> {
27672811 // anymore.
27682812 if index < values. len ( ) - 1 {
27692813 let predicate = self . build_predicate ( value) ;
2814+ let possibly_narrowed = self . compute_possibly_narrowed_places ( & predicate) ;
27702815 let predicate_id = match op {
27712816 ast:: BoolOp :: And => self . add_predicate ( predicate) ,
27722817 ast:: BoolOp :: Or => self . add_negated_predicate ( predicate) ,
@@ -2789,7 +2834,10 @@ impl<'ast> Visitor<'ast> for SemanticIndexBuilder<'_, 'ast> {
27892834 // the application of the reachability constraint until after the expression
27902835 // has been evaluated, so we only push it onto the stack here.
27912836 self . flow_restore ( after_expr) ;
2792- self . record_narrowing_constraint_id ( predicate_id) ;
2837+ self . record_narrowing_constraint_id_for_places (
2838+ predicate_id,
2839+ & possibly_narrowed,
2840+ ) ;
27932841 reachability_constraints. push ( reachability_constraint) ;
27942842 }
27952843 }
0 commit comments