@@ -98,9 +98,7 @@ use crate::report::pysa::global_variable::WholeProgramGlobalVariables;
9898use crate :: report:: pysa:: location:: PysaLocation ;
9999use crate :: report:: pysa:: module:: ModuleId ;
100100use crate :: report:: pysa:: module:: ModuleKey ;
101- use crate :: report:: pysa:: override_graph:: OverrideGraph ;
102101use crate :: report:: pysa:: types:: ScalarTypeProperties ;
103- use crate :: report:: pysa:: types:: has_superclass;
104102use crate :: report:: pysa:: types:: string_for_type;
105103use crate :: state:: lsp:: FindDefinitionItemWithDocstring ;
106104use crate :: state:: lsp:: FindPreference ;
@@ -282,26 +280,10 @@ pub trait FunctionTrait:
282280
283281impl FunctionTrait for FunctionRef { }
284282
285- /// Maximum number of targets in an override subset before we collapse it into
286- /// `OverrideSubsetThreshold`. Large subsets lead to very large call-graph JSON
287- /// files and significant slowdowns during both serialization and Pysa's
288- /// analysis. When the number of targets exceeds this threshold we fall back to
289- /// recording only the base method.
290- const OVERRIDE_SUBSET_THRESHOLD : usize = 500 ;
291-
292283#[ derive( Debug , PartialEq , Eq , Clone , Hash , Serialize , PartialOrd , Ord ) ]
293284pub enum Target < Function : FunctionTrait > {
294- Function ( Function ) , // Either a function or a method
295- AllOverrides ( Function ) , // All overrides of the given method
296- OverrideSubset {
297- base_method : Function ,
298- subset : Vec1 < Target < Function > > ,
299- } ,
300- /// Like `OverrideSubset`, but used when the number of targets in the subset
301- /// exceeds `OVERRIDE_SUBSET_THRESHOLD`.
302- OverrideSubsetThreshold {
303- base_method : Function ,
304- } ,
285+ Function ( Function ) , // Either a function or a method
286+ Overrides ( Function ) , // All overrides of the given method
305287 FormatString ,
306288}
307289
@@ -316,27 +298,15 @@ impl<Function: FunctionTrait> Target<Function> {
316298 {
317299 match self {
318300 Target :: Function ( function) => Target :: Function ( map ( function) ) ,
319- Target :: AllOverrides ( function) => Target :: AllOverrides ( map ( function) ) ,
320- Target :: OverrideSubset {
321- base_method,
322- subset,
323- } => Target :: OverrideSubset {
324- base_method : map ( base_method) ,
325- subset : Vec1 :: mapped ( subset, |target| target. map_function ( map) ) ,
326- } ,
327- Target :: OverrideSubsetThreshold { base_method } => Target :: OverrideSubsetThreshold {
328- base_method : map ( base_method) ,
329- } ,
301+ Target :: Overrides ( function) => Target :: Overrides ( map ( function) ) ,
330302 Target :: FormatString => Target :: FormatString ,
331303 }
332304 }
333305
334306 fn base_function ( & self ) -> Option < & Function > {
335307 match self {
336308 Target :: Function ( function) => Some ( function) ,
337- Target :: AllOverrides ( method) => Some ( method) ,
338- Target :: OverrideSubset { base_method, .. }
339- | Target :: OverrideSubsetThreshold { base_method } => Some ( base_method) ,
309+ Target :: Overrides ( method) => Some ( method) ,
340310 Target :: FormatString => None ,
341311 }
342312 }
@@ -1578,7 +1548,6 @@ struct CallGraphVisitor<'a> {
15781548 module_id : ModuleId ,
15791549 module_name : ModuleName ,
15801550 function_base_definitions : & ' a WholeProgramFunctionDefinitions < FunctionBaseDefinition > ,
1581- override_graph : & ' a OverrideGraph ,
15821551 global_variables : & ' a WholeProgramGlobalVariables ,
15831552 captured_variables : & ' a ModuleCapturedVariables < FunctionRef > ,
15841553 current_function : Option < FunctionRef > , // The current function, if it is exported.
@@ -1758,26 +1727,13 @@ impl<'a> CallGraphVisitor<'a> {
17581727 }
17591728
17601729 // Figure out what target to pick for an indirect call that resolves to implementation_target.
1761- // E.g., if the receiver type is A, and A derives from Base, and the target is Base.method, then
1762- // targeting the override tree of Base.method is wrong, as it would include all siblings for A.//
1763- // Instead, we have the following cases:
1764- // a) receiver type matches implementation_target's declaring type -> override implementation_target
1765- // b) no implementation_target override entries are subclasses of A -> real implementation_target
1766- // c) some override entries are subclasses of A -> search upwards for actual implementation,
1767- // and override all those where the override name is
1768- // 1) the override target if it exists in the override shared mem
1769- // 2) the real target otherwise
1730+ // The receiver_class is already part of the PysaCallTarget, so we just need to decide
1731+ // between Function (no receiver) and Overrides (has receiver).
17701732 fn compute_targets_for_virtual_call (
17711733 & self ,
1772- callee_type : Option < & Type > ,
1773- precise_receiver_type : Option < & Type > ,
1734+ receiver_type : Option < & Type > ,
17741735 callee : FunctionRef ,
17751736 ) -> Target < FunctionRef > {
1776- let receiver_type = if precise_receiver_type. is_some ( ) {
1777- precise_receiver_type
1778- } else {
1779- receiver_type_from_callee_type ( callee_type)
1780- } ;
17811737 if receiver_type. is_none ( ) {
17821738 return Target :: Function ( callee) ;
17831739 }
@@ -1793,70 +1749,9 @@ impl<'a> CallGraphVisitor<'a> {
17931749 if receiver_class. is_none ( ) {
17941750 return Target :: Function ( callee) ;
17951751 }
1796- let receiver_class = receiver_class. unwrap ( ) ;
1797-
1798- let callee_class = self
1799- . function_base_definitions
1800- . get ( callee. module_id , & callee. function_id )
1801- . and_then ( |definition| definition. defining_class . clone ( ) ) ;
1802- let callee_class = callee_class
1803- . unwrap_or_else ( || panic ! ( "Expect a callee class for callee `{:#?}`" , callee) ) ;
1804-
1805- let get_actual_target = |callee : FunctionRef | {
1806- if self . override_graph . overrides_exist ( & callee) {
1807- Target :: AllOverrides ( callee)
1808- } else {
1809- Target :: Function ( callee)
1810- }
1811- } ;
1812- if callee_class == receiver_class {
1813- // case a
1814- get_actual_target ( callee)
1815- } else if let Some ( overriding_classes) = self . override_graph . get_overriding_classes ( & callee)
1816- {
1817- // case c
1818- if overriding_classes. len ( ) > OVERRIDE_SUBSET_THRESHOLD {
1819- Target :: OverrideSubsetThreshold {
1820- base_method : callee,
1821- }
1822- } else {
1823- let mut callees = overriding_classes
1824- . iter ( )
1825- . filter_map ( |overriding_class| {
1826- if has_superclass (
1827- & overriding_class. class ,
1828- & receiver_class. class ,
1829- self . module_context ,
1830- ) {
1831- self . function_ref_from_class_field (
1832- & overriding_class. class ,
1833- & callee. function_name ,
1834- /* exclude_object_methods */ false ,
1835- )
1836- . ok ( )
1837- . map ( get_actual_target)
1838- } else {
1839- None
1840- }
1841- } )
1842- . collect :: < Vec < _ > > ( ) ;
1843-
1844- if callees. is_empty ( ) {
1845- Target :: Function ( callee)
1846- } else if callees. len ( ) == overriding_classes. len ( ) {
1847- Target :: AllOverrides ( callee)
1848- } else {
1849- callees. sort ( ) ;
1850- Target :: OverrideSubset {
1851- base_method : callee,
1852- subset : Vec1 :: try_from_vec ( callees) . unwrap ( ) ,
1853- }
1854- }
1855- }
1856- } else {
1857- // case b
1858- Target :: Function ( callee)
1859- }
1752+ // Pysa is responsible for filtering the overridden methods
1753+ // to only those from classes that extend the receiver_class.
1754+ Target :: Overrides ( callee)
18601755 }
18611756
18621757 fn call_targets_from_callable_type (
@@ -2032,22 +1927,16 @@ impl<'a> CallGraphVisitor<'a> {
20321927 override_implicit_receiver,
20331928 )
20341929 } else {
2035- let target = self . compute_targets_for_virtual_call (
2036- callee_type,
2037- precise_receiver_type,
2038- function_ref,
2039- ) ;
1930+ let target = self . compute_targets_for_virtual_call ( receiver_type, function_ref) ;
20401931 match target {
2041- Target :: Function ( _)
2042- | Target :: AllOverrides ( _)
2043- | Target :: OverrideSubset { .. }
2044- | Target :: OverrideSubsetThreshold { .. } => self . call_target_from_function_target (
2045- target,
2046- return_type,
2047- receiver_type,
2048- callee_expr_suffix,
2049- override_implicit_receiver,
2050- ) ,
1932+ Target :: Function ( _) | Target :: Overrides ( _) => self
1933+ . call_target_from_function_target (
1934+ target,
1935+ return_type,
1936+ receiver_type,
1937+ callee_expr_suffix,
1938+ override_implicit_receiver,
1939+ ) ,
20511940 Target :: FormatString => PysaCallTarget {
20521941 target,
20531942 implicit_receiver : ImplicitReceiver :: False ,
@@ -4374,7 +4263,6 @@ fn resolve_call(
43744263 call : & ExprCall ,
43754264 function_definitions : & WholeProgramFunctionDefinitions < FunctionBaseDefinition > ,
43764265 module_context : & ModuleContext ,
4377- override_graph : & OverrideGraph ,
43784266) -> Vec < PysaCallTarget < FunctionRef > > {
43794267 let mut call_graphs = CallGraphs :: new ( ) ;
43804268 let visitor = CallGraphVisitor {
@@ -4386,7 +4274,6 @@ fn resolve_call(
43864274 current_function : None ,
43874275 debug : false ,
43884276 debug_scopes : Vec :: new ( ) ,
4389- override_graph,
43904277 global_variables : & WholeProgramGlobalVariables :: new ( ) ,
43914278 captured_variables : & ModuleCapturedVariables :: new ( ) ,
43924279 error_collector : ErrorCollector :: new ( module_context. module_info . dupe ( ) , ErrorStyle :: Never ) ,
@@ -4414,7 +4301,6 @@ fn resolve_expression(
44144301 expression : & Expr ,
44154302 function_definitions : & WholeProgramFunctionDefinitions < FunctionBaseDefinition > ,
44164303 module_context : & ModuleContext ,
4417- override_graph : & OverrideGraph ,
44184304 parent_expression : Option < & Expr > ,
44194305) -> Vec < PysaCallTarget < FunctionRef > > {
44204306 // This needs to be provided. Otherwise the callees won't be registered into `call_graphs`.
@@ -4434,7 +4320,6 @@ fn resolve_expression(
44344320 current_function : Some ( current_function. clone ( ) ) ,
44354321 debug : false ,
44364322 debug_scopes : Vec :: new ( ) ,
4437- override_graph,
44384323 global_variables : & WholeProgramGlobalVariables :: new ( ) ,
44394324 captured_variables : & ModuleCapturedVariables :: new ( ) ,
44404325 error_collector : ErrorCollector :: new ( module_context. module_info . dupe ( ) , ErrorStyle :: Never ) ,
@@ -4467,19 +4352,8 @@ pub fn resolve_decorator_callees(
44674352) -> HashMap < PysaLocation , Vec < Target < FunctionRef > > > {
44684353 let mut decorator_callees = HashMap :: new ( ) ;
44694354
4470- // We do not care about overrides here
4471- let override_graph = OverrideGraph :: new ( ) ;
4472-
44734355 let is_object_new_or_init_target = |target : & Target < FunctionRef > | match target {
4474- Target :: Function ( function_ref)
4475- | Target :: AllOverrides ( function_ref)
4476- | Target :: OverrideSubset {
4477- base_method : function_ref,
4478- ..
4479- }
4480- | Target :: OverrideSubsetThreshold {
4481- base_method : function_ref,
4482- } => {
4356+ Target :: Function ( function_ref) | Target :: Overrides ( function_ref) => {
44834357 function_ref. module_name == ModuleName :: builtins ( )
44844358 && ( function_ref. function_name == dunder:: INIT
44854359 || function_ref. function_name == dunder:: NEW )
@@ -4491,8 +4365,7 @@ pub fn resolve_decorator_callees(
44914365 let ( range, callees) = match & decorator. expression {
44924366 Expr :: Call ( call) => {
44934367 // Decorator factor, e.g `@foo(1)`. We export the callee of `foo`.
4494- let callees =
4495- resolve_call ( call, function_base_definitions, context, & override_graph) ;
4368+ let callees = resolve_call ( call, function_base_definitions, context) ;
44964369 (
44974370 ( * call. func ) . range ( ) ,
44984371 callees
@@ -4507,7 +4380,6 @@ pub fn resolve_decorator_callees(
45074380 expr,
45084381 function_base_definitions,
45094382 context,
4510- & override_graph,
45114383 /* parent_expression */ None ,
45124384 ) ;
45134385 (
@@ -4536,7 +4408,6 @@ pub fn resolve_decorator_callees(
45364408pub fn export_call_graphs (
45374409 context : & ModuleContext ,
45384410 function_base_definitions : & WholeProgramFunctionDefinitions < FunctionBaseDefinition > ,
4539- override_graph : & OverrideGraph ,
45404411 global_variables : & WholeProgramGlobalVariables ,
45414412 captured_variables : & WholeProgramCapturedVariables ,
45424413) -> CallGraphs < ExpressionIdentifier , FunctionRef > {
@@ -4552,7 +4423,6 @@ pub fn export_call_graphs(
45524423 current_function : None ,
45534424 debug : false ,
45544425 debug_scopes : Vec :: new ( ) ,
4555- override_graph,
45564426 global_variables,
45574427 captured_variables : captured_variables
45584428 . get_for_module ( context. module_id )
0 commit comments