From 167c98b3653a8e50cf3a674a4787e1a9cf63dba7 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Wed, 20 Mar 2024 22:51:10 -0400 Subject: [PATCH] Store template types in vecs for compactness --- src/analyzer/dataflow/program_analyzer.rs | 11 ++--- .../instance_property_assignment_analyzer.rs | 2 +- src/analyzer/expr/call/arguments_analyzer.rs | 42 ++++++++++--------- .../call/class_template_param_collector.rs | 32 +++++++------- .../existing_atomic_method_call_analyzer.rs | 2 +- .../call/function_call_return_type_fetcher.rs | 7 ++-- src/analyzer/expr/call/new_analyzer.rs | 8 ++-- src/analyzer/expr/call_analyzer.rs | 8 +++- .../fetch/atomic_property_fetch_analyzer.rs | 8 +++- src/analyzer/functionlike_analyzer.rs | 4 +- src/code_info/classlike_info.rs | 6 +-- src/code_info/data_flow/graph.rs | 4 +- src/code_info/data_flow/tainted_node.rs | 2 +- src/code_info/functionlike_info.rs | 7 ++-- src/code_info/functionlike_parameter.rs | 4 +- src/code_info/t_atomic.rs | 2 +- src/code_info/type_definition_info.rs | 3 +- src/code_info/type_resolution.rs | 5 +-- src/code_info_builder/classlike_scanner.rs | 22 ++++------ src/code_info_builder/functionlike_scanner.rs | 40 +++++++++++------- src/code_info_builder/lib.rs | 19 ++++----- src/code_info_builder/typehint_resolver.rs | 13 +++--- src/file_scanner_analyzer/populator.rs | 13 +++--- src/file_scanner_analyzer/scanner.rs | 3 ++ src/file_scanner_analyzer/unused_symbols.rs | 10 ++++- src/str/lib.rs | 2 +- src/ttype/template/mod.rs | 4 +- src/ttype/template/standin_type_replacer.rs | 36 +++++++++------- src/ttype/type_expander.rs | 8 ++-- 29 files changed, 175 insertions(+), 152 deletions(-) diff --git a/src/analyzer/dataflow/program_analyzer.rs b/src/analyzer/dataflow/program_analyzer.rs index 578998f1..a25dcdaa 100644 --- a/src/analyzer/dataflow/program_analyzer.rs +++ b/src/analyzer/dataflow/program_analyzer.rs @@ -216,7 +216,7 @@ fn get_specialized_sources( new_source .specialized_calls - .entry(specialization_key.clone()) + .entry(*specialization_key) .or_default() .insert(new_source.id.clone()); @@ -227,11 +227,7 @@ fn get_specialized_sources( if source.specialized_calls.is_empty() || source.specialized_calls.contains_key(specialization) { - let new_id = format!( - "{}-{}", - source.id, - format!("{}:{}", specialization.0 .0, specialization.1) - ); + let new_id = format!("{}-{}:{}", source.id, specialization.0 .0, specialization.1); if graph.forward_edges.contains_key(&new_id) { let mut new_source = (*source).clone(); @@ -247,8 +243,7 @@ fn get_specialized_sources( } else { for (key, map) in &source.specialized_calls { if map.contains(&source.id) { - let new_forward_edge_id = - format!("{}-{}", source.id, format!("{}:{}", key.0 .0, key.1)); + let new_forward_edge_id = format!("{}-{}:{}", source.id, key.0 .0, key.1); if graph.forward_edges.contains_key(&new_forward_edge_id) { let mut new_source = (*source).clone(); diff --git a/src/analyzer/expr/assignment/instance_property_assignment_analyzer.rs b/src/analyzer/expr/assignment/instance_property_assignment_analyzer.rs index 50d1ce5f..20633b2d 100644 --- a/src/analyzer/expr/assignment/instance_property_assignment_analyzer.rs +++ b/src/analyzer/expr/assignment/instance_property_assignment_analyzer.rs @@ -685,7 +685,7 @@ fn add_instance_property_assignment_dataflow( if !stmt_type_inner .parent_nodes .iter() - .any(|n| &n.id == &var_node.id) + .any(|n| n.id == var_node.id) { stmt_type_inner.parent_nodes.push(var_node.clone()); } diff --git a/src/analyzer/expr/call/arguments_analyzer.rs b/src/analyzer/expr/call/arguments_analyzer.rs index 78ed922a..e72c8c6a 100644 --- a/src/analyzer/expr/call/arguments_analyzer.rs +++ b/src/analyzer/expr/call/arguments_analyzer.rs @@ -156,11 +156,11 @@ pub(crate) fn check_arguments_match( if lower_bounds.len() == 1 { class_generic_params .entry(*template_name) - .or_insert_with(FxHashMap::default) - .insert( + .or_insert_with(Vec::new) + .push(( *class, Arc::new(lower_bounds.first().unwrap().bound_type.clone()), - ); + )); } } } @@ -520,7 +520,7 @@ pub(crate) fn check_arguments_match( } fn adjust_param_type( - class_generic_params: &IndexMap>>, + class_generic_params: &IndexMap)>>, param_type: &mut TUnion, codebase: &CodebaseInfo, mut arg_value_type: TUnion, @@ -712,10 +712,10 @@ fn handle_closure_arg( )), ) }) - .collect::>(), + .collect::>(), ) }) - .collect::>(), + .collect(), IndexMap::new(), ); @@ -806,7 +806,7 @@ fn handle_closure_arg( | StrId::LIB_KEYSET_MAP_WITH_KEY | StrId::LIB_DICT_MAP_WITH_KEY_ASYNC | StrId::LIB_DICT_FROM_KEYS - | StrId::LIB_DICT_FROM_KEYS_ASYNC => { + | StrId::LIB_DICT_FROM_KEYS_ASYNC => { if param_offset == 0 { if let Some(ref mut signature_type) = param_storage.signature_type { add_array_fetch_dataflow( @@ -833,7 +833,7 @@ fn handle_closure_arg( } fn map_class_generic_params( - class_generic_params: &IndexMap>>, + class_generic_params: &IndexMap)>>, param_type: &mut TUnion, codebase: &CodebaseInfo, interner: &Interner, @@ -1083,7 +1083,7 @@ fn refine_template_result_for_functionlike( classlike_storage: Option<&ClassLikeInfo>, calling_classlike_storage: Option<&ClassLikeInfo>, functionlike_storage: &FunctionLikeInfo, - class_template_params: &IndexMap>>, + class_template_params: &IndexMap)>>, ) { let template_types = get_template_types_for_call( codebase, @@ -1117,10 +1117,11 @@ pub(crate) fn get_template_types_for_call( declaring_classlike_storage: Option<&ClassLikeInfo>, appearing_class_name: Option<&StrId>, calling_classlike_storage: Option<&ClassLikeInfo>, - existing_template_types: &IndexMap>>, - class_template_params: &IndexMap>>, + existing_template_types: &[(StrId, Vec<(StrId, Arc)>)], + class_template_params: &IndexMap)>>, ) -> IndexMap> { - let mut template_types = existing_template_types.clone(); + let mut template_types: IndexMap)>> = + IndexMap::from_iter(existing_template_types.to_owned()); if let Some(declaring_classlike_storage) = declaring_classlike_storage { let calling_has_extends = if let Some(calling_classlike_storage) = calling_classlike_storage @@ -1177,8 +1178,8 @@ pub(crate) fn get_template_types_for_call( template_types .entry(*template_name) - .or_insert_with(FxHashMap::default) - .insert(declaring_classlike_storage.name, output_type); + .or_insert_with(Vec::new) + .push((declaring_classlike_storage.name, output_type)); } } } @@ -1187,16 +1188,19 @@ pub(crate) fn get_template_types_for_call( for (key, type_) in type_map { template_types .entry(*template_name) - .or_insert_with(FxHashMap::default) - .insert( + .or_insert_with(Vec::new) + .push(( *key, class_template_params .get(template_name) - .unwrap_or(&FxHashMap::default()) - .get(key) + .unwrap_or(&vec![]) + .iter() + .filter(|(k, _)| k == key) + .map(|(_, v)| v) + .next() .cloned() .unwrap_or(type_.clone()), - ); + )); } } } diff --git a/src/analyzer/expr/call/class_template_param_collector.rs b/src/analyzer/expr/call/class_template_param_collector.rs index 7811a08b..99b1afc5 100644 --- a/src/analyzer/expr/call/class_template_param_collector.rs +++ b/src/analyzer/expr/call/class_template_param_collector.rs @@ -33,7 +33,7 @@ pub(crate) fn collect( if class_storage.name == static_class_storage.name && !static_class_storage.template_types.is_empty() { - for (i, type_name) in class_storage.template_types.keys().enumerate() { + for (i, (type_name, _)) in class_storage.template_types.iter().enumerate() { if let Some(type_param) = lhs_type_params.get(i) { class_template_params .entry(*type_name) @@ -139,22 +139,20 @@ pub(crate) fn resolve_template_param( .. } = &type_extends_atomic { - if static_class_storage + if let Some(entry) = static_class_storage .template_types - .get(param_name) - .unwrap_or(&FxHashMap::default()) - .contains_key(defining_entity) + .iter() + .enumerate() + .find(|(_, (k, _))| k == param_name) { - let mapped_offset = static_class_storage.template_types.get_index_of(param_name); - - if let Some(mapped_offset) = mapped_offset { - if let Some(type_param) = type_params.get(mapped_offset) { - output_type_extends = Some(add_optional_union_type( - type_param.clone(), - output_type_extends.as_ref(), - codebase, - )); - } + let mapped_offset = entry.0; + + if let Some(type_param) = type_params.get(mapped_offset) { + output_type_extends = Some(add_optional_union_type( + type_param.clone(), + output_type_extends.as_ref(), + codebase, + )); } } else if let Some(input_type_extends) = static_class_storage .template_extended_params @@ -193,7 +191,7 @@ fn expand_type( input_type_extends: &Arc, e: &FxHashMap>>, static_classlike_name: &StrId, - static_template_types: &IndexMap>>, + static_template_types: &Vec<(StrId, Vec<(StrId, Arc)>)>, ) -> Vec { let mut output_type_extends = Vec::new(); @@ -205,7 +203,7 @@ fn expand_type( } = type_extends_atomic { if static_classlike_name != defining_entity - || !static_template_types.contains_key(param_name) + || !static_template_types.iter().any(|(k, _)| k == param_name) { if let Some(extended_type_map) = e.get(defining_entity) { extended_type_map.get(param_name) diff --git a/src/analyzer/expr/call/existing_atomic_method_call_analyzer.rs b/src/analyzer/expr/call/existing_atomic_method_call_analyzer.rs index 2f1d8a04..849331a7 100644 --- a/src/analyzer/expr/call/existing_atomic_method_call_analyzer.rs +++ b/src/analyzer/expr/call/existing_atomic_method_call_analyzer.rs @@ -138,7 +138,7 @@ pub(crate) fn analyze( let functionlike_template_types = functionlike_storage.template_types.clone(); let mut template_result = TemplateResult::new( - functionlike_template_types, + IndexMap::from_iter(functionlike_template_types), class_template_params.clone().unwrap_or(IndexMap::new()), ); diff --git a/src/analyzer/expr/call/function_call_return_type_fetcher.rs b/src/analyzer/expr/call/function_call_return_type_fetcher.rs index 990b8f06..fa93faa3 100644 --- a/src/analyzer/expr/call/function_call_return_type_fetcher.rs +++ b/src/analyzer/expr/call/function_call_return_type_fetcher.rs @@ -76,14 +76,13 @@ pub(crate) fn fetch( if !function_storage.template_types.is_empty() && !function_storage.template_types.is_empty() { - let fn_id = statements_analyzer - .get_interner() + let interner = statements_analyzer.get_interner(); + let fn_id = interner .get( format!( "fn-{}", match functionlike_id { - FunctionLikeIdentifier::Function(function_id) => - function_id.0.to_string(), + FunctionLikeIdentifier::Function(function_id) => function_id.0, FunctionLikeIdentifier::Method(_, _) => panic!(), _ => { panic!() diff --git a/src/analyzer/expr/call/new_analyzer.rs b/src/analyzer/expr/call/new_analyzer.rs index d12189fd..cdcbf46a 100644 --- a/src/analyzer/expr/call/new_analyzer.rs +++ b/src/analyzer/expr/call/new_analyzer.rs @@ -343,7 +343,7 @@ fn analyze_named_constructor( if expr.1.is_empty() { IndexMap::new() } else { - storage.template_types.clone() + IndexMap::from_iter(storage.template_types.clone()) }, IndexMap::new(), ); @@ -401,7 +401,7 @@ fn analyze_named_constructor( let placeholder_name = format!("`_{}", analysis_data.type_variable_bounds.len()); - let upper_bound = (**map.iter().next().unwrap().1).clone(); + let upper_bound = (*map.iter().next().unwrap().1).clone(); let mut placeholder_lower_bounds = vec![]; @@ -503,7 +503,7 @@ fn analyze_named_constructor( )), ) }) - .collect::>(), + .collect::>(), ) }) .collect::>(); @@ -518,7 +518,7 @@ fn analyze_named_constructor( } else if let Some(Variance::Contravariant) = storage.generic_variance.get(&i) { get_nothing() } else { - (**base_type_map.iter().next().unwrap().1).clone() + (*base_type_map.iter().next().unwrap().1).clone() }; generic_param_type.had_template = true; diff --git a/src/analyzer/expr/call_analyzer.rs b/src/analyzer/expr/call_analyzer.rs index 051c10f3..e91d54bb 100644 --- a/src/analyzer/expr/call_analyzer.rs +++ b/src/analyzer/expr/call_analyzer.rs @@ -321,11 +321,15 @@ pub(crate) fn get_generic_param_for_offset( classlike_name: &StrId, template_name: &StrId, template_extended_params: &FxHashMap>>, - found_generic_params: &FxHashMap>>, + found_generic_params: &FxHashMap)>>, ) -> Arc { if let Some(found_generic_param) = if let Some(result_map) = found_generic_params.get(template_name) { - result_map.get(classlike_name) + result_map + .iter() + .filter(|(e, _)| e == classlike_name) + .map(|(_, v)| v) + .next() } else { None } diff --git a/src/analyzer/expr/fetch/atomic_property_fetch_analyzer.rs b/src/analyzer/expr/fetch/atomic_property_fetch_analyzer.rs index 9289b60e..fbc806c2 100644 --- a/src/analyzer/expr/fetch/atomic_property_fetch_analyzer.rs +++ b/src/analyzer/expr/fetch/atomic_property_fetch_analyzer.rs @@ -255,7 +255,7 @@ fn get_class_property_type( let mut type_params = vec![]; for (_, type_map) in &declaring_class_storage.template_types { - type_params.push((**type_map.iter().next().unwrap().1).clone()); + type_params.push((*type_map.iter().next().unwrap().1).clone()); } lhs_type_part = TAtomic::TNamedObject { @@ -353,7 +353,11 @@ pub(crate) fn localize_property_type( if let TAtomic::TGenericParam { param_name, .. } = &mapped_type_atomic { let position = property_class_storage .template_types - .get_index_of(param_name); + .iter() + .enumerate() + .filter(|(_, (k, _))| k == param_name) + .map(|(i, _)| i) + .next(); if let Some(position) = position { if let Some(mapped_param) = lhs_type_params.get(position) { diff --git a/src/analyzer/functionlike_analyzer.rs b/src/analyzer/functionlike_analyzer.rs index 069a0a98..1f7420ff 100644 --- a/src/analyzer/functionlike_analyzer.rs +++ b/src/analyzer/functionlike_analyzer.rs @@ -290,8 +290,8 @@ impl<'a> FunctionLikeAnalyzer<'a> { wrap_atomic(TAtomic::TGenericParam { param_name: *param_name, - as_type: Box::new((**first_map_entry.1).clone()), - defining_entity: *first_map_entry.0, + as_type: Box::new((*first_map_entry.1).clone()), + defining_entity: first_map_entry.0, from_class: false, extra_types: None, }) diff --git a/src/code_info/classlike_info.rs b/src/code_info/classlike_info.rs index 27daf74e..dd0fadb1 100644 --- a/src/code_info/classlike_info.rs +++ b/src/code_info/classlike_info.rs @@ -131,7 +131,7 @@ pub struct ClassLikeInfo { * (i.e. the same as the class name). This allows operations with the same-named template defined * across multiple classes to not run into trouble. */ - pub template_types: IndexMap>>, + pub template_types: Vec<(StrId, Vec<(StrId, Arc)>)>, /* * A list of all the templates that are only written in the constructor. @@ -216,7 +216,7 @@ impl ClassLikeInfo { ) -> ClassLikeInfo { ClassLikeInfo { meta_start, - constants: IndexMap::default(), + constants: IndexMap::new(), is_populated: false, is_stubbed: false, is_deprecated: false, @@ -263,7 +263,7 @@ impl ClassLikeInfo { template_extended_offsets: FxHashMap::default(), template_type_implements_count: FxHashMap::default(), template_type_uses_count: FxHashMap::default(), - template_types: IndexMap::new(), + template_types: vec![], used_traits: FxHashSet::default(), name, type_constants: FxHashMap::default(), diff --git a/src/code_info/data_flow/graph.rs b/src/code_info/data_flow/graph.rs index ca90311c..d58cc3d0 100644 --- a/src/code_info/data_flow/graph.rs +++ b/src/code_info/data_flow/graph.rs @@ -61,10 +61,10 @@ impl DataFlowGraph { self.specializations .entry(unspecialized_id.clone()) .or_default() - .insert(specialization_key.clone()); + .insert(*specialization_key); self.specialized_calls - .entry(specialization_key.clone()) + .entry(*specialization_key) .or_default() .insert(unspecialized_id.clone()); } diff --git a/src/code_info/data_flow/tainted_node.rs b/src/code_info/data_flow/tainted_node.rs index 5b3dd7b9..01a85547 100644 --- a/src/code_info/data_flow/tainted_node.rs +++ b/src/code_info/data_flow/tainted_node.rs @@ -83,7 +83,7 @@ impl TaintedNode { unspecialized_id: unspecialized_id.clone(), label: label.clone(), pos: pos.as_ref().map(|p| Arc::new(*p)), - specialization_key: specialization_key.clone(), + specialization_key: *specialization_key, taint_sinks: vec![], previous: None, path_types: Vec::new(), diff --git a/src/code_info/functionlike_info.rs b/src/code_info/functionlike_info.rs index 55766602..8567f8cf 100644 --- a/src/code_info/functionlike_info.rs +++ b/src/code_info/functionlike_info.rs @@ -1,7 +1,6 @@ use std::sync::Arc; use hakana_str::StrId; -use indexmap::IndexMap; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; @@ -72,7 +71,7 @@ pub struct FunctionLikeInfo { pub is_populated: bool, - pub suppressed_issues: Option>, + pub suppressed_issues: Option>, pub deprecated: bool, @@ -85,7 +84,7 @@ pub struct FunctionLikeInfo { * function identifier. This allows operations with the same-named template defined * across multiple classes and/or functions to not run into trouble. */ - pub template_types: IndexMap>>, + pub template_types: Vec<(StrId, Vec<(StrId, Arc)>)>, pub assertions: Option>, @@ -175,7 +174,7 @@ impl FunctionLikeInfo { user_defined: false, suppressed_issues: None, deprecated: false, - template_types: IndexMap::new(), + template_types: vec![], assertions: None, if_true_assertions: None, if_false_assertions: None, diff --git a/src/code_info/functionlike_parameter.rs b/src/code_info/functionlike_parameter.rs index 3c0f8ab4..1a3ff75c 100644 --- a/src/code_info/functionlike_parameter.rs +++ b/src/code_info/functionlike_parameter.rs @@ -1,5 +1,3 @@ -use rustc_hash::FxHashMap; - use serde::{Deserialize, Serialize}; use crate::{ @@ -58,7 +56,7 @@ pub struct FunctionLikeParameter { pub attributes: Vec, - pub suppressed_issues: Option>, + pub suppressed_issues: Option>, } impl FunctionLikeParameter { diff --git a/src/code_info/t_atomic.rs b/src/code_info/t_atomic.rs index 02608cf8..6ccd9901 100644 --- a/src/code_info/t_atomic.rs +++ b/src/code_info/t_atomic.rs @@ -1299,7 +1299,7 @@ impl TAtomic { ref mut as_type, .. } = type_part { - as_type.clone_from(&extends_as_type); + as_type.clone_from(extends_as_type); } new_intersection_types.push(type_part); diff --git a/src/code_info/type_definition_info.rs b/src/code_info/type_definition_info.rs index 8509c168..0177194e 100644 --- a/src/code_info/type_definition_info.rs +++ b/src/code_info/type_definition_info.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use hakana_str::StrId; use rustc_hash::FxHashMap; -use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use crate::{ @@ -30,7 +29,7 @@ pub struct TypeDefinitionInfo { * function identifier. This allows operations with the same-named template defined * across multiple classes and/or functions to not run into trouble. */ - pub template_types: IndexMap>>, + pub template_types: Vec<(StrId, Vec<(StrId, Arc)>)>, pub generic_variance: FxHashMap, diff --git a/src/code_info/type_resolution.rs b/src/code_info/type_resolution.rs index b146261a..330f2a5b 100644 --- a/src/code_info/type_resolution.rs +++ b/src/code_info/type_resolution.rs @@ -3,14 +3,13 @@ use std::sync::Arc; use hakana_str::StrId; use rustc_hash::FxHashMap; -use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use crate::t_union::TUnion; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct TypeResolutionContext { - pub template_type_map: IndexMap>>, + pub template_type_map: Vec<(StrId, Vec<(StrId, Arc)>)>, pub template_supers: FxHashMap, } @@ -23,7 +22,7 @@ impl Default for TypeResolutionContext { impl TypeResolutionContext { pub fn new() -> Self { Self { - template_type_map: IndexMap::new(), + template_type_map: vec![], template_supers: FxHashMap::default(), } } diff --git a/src/code_info_builder/classlike_scanner.rs b/src/code_info_builder/classlike_scanner.rs index 202a7fe7..f0759f77 100644 --- a/src/code_info_builder/classlike_scanner.rs +++ b/src/code_info_builder/classlike_scanner.rs @@ -20,7 +20,6 @@ use hakana_reflection_info::{ FileSource, }; use hakana_type::{get_mixed_any, get_named_object, wrap_atomic}; -use indexmap::IndexMap; use oxidized::{ aast::{self, ClassConstKind}, ast_defs::{self, ClassishKind}, @@ -57,7 +56,7 @@ pub(crate) fn scan( comments, &mut meta_start, file_source, - &mut FxHashMap::default(), + &mut vec![], all_custom_issues, ); @@ -83,7 +82,7 @@ pub(crate) fn scan( if !classlike_node.tparams.is_empty() { let mut type_context = TypeResolutionContext { - template_type_map: IndexMap::new(), + template_type_map: vec![], template_supers: FxHashMap::default(), }; @@ -91,10 +90,9 @@ pub(crate) fn scan( let param_name = resolved_names .get(&(type_param_node.name.0.start_offset() as u32)) .unwrap(); - type_context.template_type_map.insert( - *param_name, - FxHashMap::from_iter([(*class_name, Arc::new(get_mixed_any()))]), - ); + type_context + .template_type_map + .push((*param_name, vec![(*class_name, Arc::new(get_mixed_any()))])); } for (i, type_param_node) in classlike_node.tparams.iter().enumerate() { @@ -130,11 +128,9 @@ pub(crate) fn scan( .get(&(type_param_node.name.0.start_offset() as u32)) .unwrap(); - storage.template_types.insert(*param_name, { - let mut h = FxHashMap::default(); - h.insert(*class_name, Arc::new(template_as_type)); - h - }); + storage + .template_types + .push((*param_name, vec![(*class_name, Arc::new(template_as_type))])); match type_param_node.variance { ast_defs::Variance::Covariant => { @@ -707,7 +703,7 @@ fn visit_xhp_attribute( &hint.1, None, &TypeResolutionContext { - template_type_map: IndexMap::new(), + template_type_map: vec![], template_supers: FxHashMap::default(), }, resolved_names, diff --git a/src/code_info_builder/functionlike_scanner.rs b/src/code_info_builder/functionlike_scanner.rs index 8d0b835a..a06aca0d 100644 --- a/src/code_info_builder/functionlike_scanner.rs +++ b/src/code_info_builder/functionlike_scanner.rs @@ -163,7 +163,7 @@ pub(crate) fn get_functionlike( ) -> FunctionLikeInfo { let definition_location = HPos::new(def_pos, file_source.file_path, None); - let mut suppressed_issues = FxHashMap::default(); + let mut suppressed_issues = vec![]; let mut meta_start = MetaStart { start_offset: definition_location.start_offset, @@ -195,10 +195,9 @@ pub(crate) fn get_functionlike( let param_name = resolved_names .get(&(type_param_node.name.0.start_offset() as u32)) .unwrap(); - type_context.template_type_map.insert( - *param_name, - FxHashMap::from_iter([(fn_id, Arc::new(get_mixed_any()))]), - ); + type_context + .template_type_map + .push((*param_name, vec![(fn_id, Arc::new(get_mixed_any()))])); } for type_param_node in tparams.iter() { @@ -251,12 +250,10 @@ pub(crate) fn get_functionlike( } } - functionlike_info.template_types.insert(*param_name, { - FxHashMap::from_iter([( - fn_id, - Arc::new(template_as_type.unwrap_or(get_mixed_any())), - )]) - }); + functionlike_info.template_types.push(( + *param_name, + vec![(fn_id, Arc::new(template_as_type.unwrap_or(get_mixed_any())))], + )); } for where_hint in where_constraints { @@ -295,6 +292,20 @@ pub(crate) fn get_functionlike( .template_type_map .extend(functionlike_info.template_types.clone()); + for row in &functionlike_info.template_types { + let mut matched = false; + for existing_template_type in type_context.template_type_map.iter_mut() { + if existing_template_type.0 == row.0 { + existing_template_type.1.clone_from(&row.1); + matched = true; + break; + } + } + if !matched { + type_context.template_type_map.push((row.0, row.1.clone())); + } + } + if !params.is_empty() { functionlike_info.params = convert_param_nodes( params, @@ -307,6 +318,7 @@ pub(crate) fn get_functionlike( .filter(|comment| comment.0.start_offset() > def_pos.start_offset()) .collect(), ); + functionlike_info.params.shrink_to_fit(); } type_context.template_supers = template_supers; @@ -554,7 +566,7 @@ pub(crate) fn adjust_location_from_comments( comments: &Vec<(Pos, Comment)>, meta_start: &mut MetaStart, file_source: &FileSource, - suppressed_issues: &mut FxHashMap, + suppressed_issues: &mut Vec<(IssueKind, HPos)>, all_custom_issues: &FxHashSet, ) { if !comments.is_empty() { @@ -582,7 +594,7 @@ pub(crate) fn adjust_location_from_comments( get_issue_from_comment(trimmed_text, all_custom_issues) { let comment_pos = HPos::new(comment_pos, file_source.file_path, None); - suppressed_issues.insert(issue_kind, comment_pos); + suppressed_issues.push((issue_kind, comment_pos)); } meta_start.start_line = start_line as u32; @@ -615,7 +627,7 @@ fn convert_param_nodes( as u16; } - let mut suppressed_issues = FxHashMap::default(); + let mut suppressed_issues = vec![]; let mut meta_start = MetaStart { start_offset: location.start_offset, diff --git a/src/code_info_builder/lib.rs b/src/code_info_builder/lib.rs index c6695b7f..d66ced59 100644 --- a/src/code_info_builder/lib.rs +++ b/src/code_info_builder/lib.rs @@ -16,7 +16,6 @@ use hakana_reflection_info::{ }; use hakana_str::{StrId, ThreadedInterner}; use hakana_type::{get_bool, get_int, get_mixed_any, get_string}; -use indexmap::IndexMap; use no_pos_hash::{position_insensitive_hash, Hasher}; use oxidized::ast::{FunParam, Tparam, TypeHint}; use oxidized::ast_defs::Id; @@ -203,7 +202,7 @@ impl<'ast> Visitor<'ast> for Scanner<'_> { .get(&(typedef.name.0.start_offset() as u32)) .unwrap(); - let mut template_type_map = IndexMap::new(); + let mut template_type_map = vec![]; let mut generic_variance = FxHashMap::default(); @@ -214,10 +213,9 @@ impl<'ast> Visitor<'ast> for Scanner<'_> { .resolved_names .get(&(type_param_node.name.0.start_offset() as u32)) .unwrap(); - type_context.template_type_map.insert( - *param_name, - FxHashMap::from_iter([(type_name, Arc::new(get_mixed_any()))]), - ); + type_context + .template_type_map + .push((*param_name, vec![(type_name, Arc::new(get_mixed_any()))])); } for (i, param) in typedef.tparams.iter().enumerate() { @@ -237,12 +235,11 @@ impl<'ast> Visitor<'ast> for Scanner<'_> { get_mixed_any() }; - let mut h = FxHashMap::default(); - h.insert( + let h = vec![( self.interner .intern("typedef-".to_string() + &type_name.0.to_string()), Arc::new(constraint_type.clone()), - ); + )]; match param.variance { ast_defs::Variance::Covariant => { @@ -261,7 +258,7 @@ impl<'ast> Visitor<'ast> for Scanner<'_> { .get(&(param.name.0.start_offset() as u32)) .unwrap(); - template_type_map.insert(*param_name, h); + template_type_map.push((*param_name, h)); } let mut definition_location = HPos::new(&typedef.span, self.file_source.file_path, None); @@ -662,7 +659,7 @@ impl<'a> Scanner<'a> { let mut template_type_map = if let Some(parent_function_storage) = parent_function_storage { parent_function_storage.template_types.clone() } else { - IndexMap::new() + vec![] }; if let Some(classlike_name) = &c.classlike_name { diff --git a/src/code_info_builder/typehint_resolver.rs b/src/code_info_builder/typehint_resolver.rs index 03299024..e49a5298 100644 --- a/src/code_info_builder/typehint_resolver.rs +++ b/src/code_info_builder/typehint_resolver.rs @@ -449,7 +449,11 @@ fn get_reference_type( return TAtomic::TMixed; }; - if let Some(defining_entities) = type_context.template_type_map.get(resolved_name) { + if let Some((_, defining_entities)) = type_context + .template_type_map + .iter() + .find(|(n, _)| n == resolved_name) + { return get_template_type(defining_entities, resolved_name); } @@ -463,11 +467,8 @@ fn get_reference_type( } } -fn get_template_type( - defining_entities: &FxHashMap>, - type_name: &StrId, -) -> TAtomic { - let (defining_entity, as_type) = defining_entities.iter().next().unwrap(); +fn get_template_type(defining_entities: &[(StrId, Arc)], type_name: &StrId) -> TAtomic { + let (defining_entity, as_type) = &defining_entities[0]; TAtomic::TGenericParam { param_name: *type_name, diff --git a/src/file_scanner_analyzer/populator.rs b/src/file_scanner_analyzer/populator.rs index 74569e4b..a691c545 100644 --- a/src/file_scanner_analyzer/populator.rs +++ b/src/file_scanner_analyzer/populator.rs @@ -93,7 +93,7 @@ pub fn populate_codebase( } for (_, map) in storage.template_types.iter_mut() { - for v in map.values_mut() { + for (_, v) in map { if v.needs_population() || userland_force_repopulation { populate_union_type( Arc::make_mut(v), @@ -304,7 +304,7 @@ fn populate_functionlike_storage( } for (_, type_param_map) in storage.template_types.iter_mut() { - for v in type_param_map.values_mut() { + for (_, v) in type_param_map { if force_type_population || v.needs_population() { populate_union_type( Arc::make_mut(v), @@ -920,8 +920,11 @@ fn extend_template_params(storage: &mut ClassLikeInfo, parent_storage: &ClassLik if let Some(parent_offsets) = storage.template_extended_offsets.get(&parent_storage.name) { for (i, extended_type) in parent_offsets.iter().enumerate() { - let parent_template_type_names = - parent_storage.template_types.keys().collect::>(); + let parent_template_type_names = parent_storage + .template_types + .iter() + .map(|(k, _)| k) + .collect::>(); let mapped_name = parent_template_type_names.get(i).cloned(); @@ -946,7 +949,7 @@ fn extend_template_params(storage: &mut ClassLikeInfo, parent_storage: &ClassLik } } else { for (template_name, template_type_map) in &parent_storage.template_types { - for template_type in template_type_map.values() { + for (_, template_type) in template_type_map { storage .template_extended_params .entry(parent_storage.name) diff --git a/src/file_scanner_analyzer/scanner.rs b/src/file_scanner_analyzer/scanner.rs index e38feb55..acf0bc53 100644 --- a/src/file_scanner_analyzer/scanner.rs +++ b/src/file_scanner_analyzer/scanner.rs @@ -480,6 +480,9 @@ pub fn scan_files( codebase.functionlike_infos.shrink_to_fit(); codebase.classlike_infos.shrink_to_fit(); + codebase.type_definitions.shrink_to_fit(); + codebase.constant_infos.shrink_to_fit(); + codebase.files.shrink_to_fit(); } Ok(ScanFilesResult { diff --git a/src/file_scanner_analyzer/unused_symbols.rs b/src/file_scanner_analyzer/unused_symbols.rs index 61e63317..f0d7fb68 100644 --- a/src/file_scanner_analyzer/unused_symbols.rs +++ b/src/file_scanner_analyzer/unused_symbols.rs @@ -50,7 +50,10 @@ pub(crate) fn find_unused_definitions( if !referenced_symbols_and_members.contains(&functionlike_name) { if let Some(suppressed_issues) = &functionlike_info.suppressed_issues { - if suppressed_issues.contains_key(&IssueKind::UnusedFunction) { + if suppressed_issues + .iter() + .any(|(i, _)| i == &IssueKind::UnusedFunction) + { continue; } } @@ -228,7 +231,10 @@ pub(crate) fn find_unused_definitions( let method_storage = functionlike_storage.method_info.as_ref().unwrap(); if let Some(suppressed_issues) = &functionlike_storage.suppressed_issues { - if suppressed_issues.contains_key(&IssueKind::UnusedPrivateMethod) { + if suppressed_issues + .iter() + .any(|(i, _)| i == &IssueKind::UnusedPrivateMethod) + { continue; } } diff --git a/src/str/lib.rs b/src/str/lib.rs index b9118b72..695dbea1 100644 --- a/src/str/lib.rs +++ b/src/str/lib.rs @@ -71,7 +71,7 @@ pub struct ThreadedInterner { impl ThreadedInterner { pub fn new(interner: Arc>) -> Self { ThreadedInterner { - map: IndexMap::default(), + map: IndexMap::new(), reverse_map: BTreeMap::new(), parent: interner.clone(), } diff --git a/src/ttype/template/mod.rs b/src/ttype/template/mod.rs index 96f779da..92778bb8 100644 --- a/src/ttype/template/mod.rs +++ b/src/ttype/template/mod.rs @@ -28,7 +28,7 @@ pub mod standin_type_replacer; */ #[derive(Clone, Debug)] pub struct TemplateResult { - pub template_types: IndexMap>>, + pub template_types: IndexMap)>>, pub lower_bounds: IndexMap>>, pub upper_bounds: IndexMap>, /** @@ -40,7 +40,7 @@ pub struct TemplateResult { impl TemplateResult { pub fn new( - template_types: IndexMap>>, + template_types: IndexMap)>>, lower_bounds: IndexMap>, ) -> TemplateResult { let mut new_lower_bounds = IndexMap::new(); diff --git a/src/ttype/template/standin_type_replacer.rs b/src/ttype/template/standin_type_replacer.rs index 0e8e8477..b15c57d8 100644 --- a/src/ttype/template/standin_type_replacer.rs +++ b/src/ttype/template/standin_type_replacer.rs @@ -1258,7 +1258,10 @@ fn handle_template_param_class_standin( .template_types .get(param_name) .unwrap() - .get(defining_entity) + .iter() + .filter(|(e, _)| e == defining_entity) + .map(|(_, v)| v) + .next() .unwrap(); for template_atomic_type in &template_type.types { @@ -1430,7 +1433,10 @@ fn handle_template_param_type_standin( .template_types .get(param_name) .unwrap() - .get(defining_entity) + .iter() + .filter(|(e, _)| e == defining_entity) + .map(|(_, v)| v) + .next() .unwrap(); for template_atomic_type in &template_type.types { @@ -1509,12 +1515,16 @@ pub fn get_actual_type_from_literal(name: &StrId, codebase: &CodebaseInfo) -> Ve } fn template_types_contains<'a>( - template_types: &'a IndexMap>>, + template_types: &'a IndexMap)>>, param_name: &StrId, defining_entity: &StrId, ) -> Option<&'a Arc> { if let Some(mapped_classes) = template_types.get(param_name) { - return mapped_classes.get(defining_entity); + return mapped_classes + .iter() + .filter(|(e, _)| e == defining_entity) + .map(|(_, v)| v) + .next(); } None @@ -1824,24 +1834,20 @@ pub fn get_mapped_generic_type_params( .. }) = ets.first() { - if let Some(defining_classes) = - input_class_storage.template_types.get(param_name) + if let Some((old_params_offset, (_, defining_classes))) = input_class_storage + .template_types + .iter() + .enumerate() + .find(|(_, (n, _))| n == param_name) { - if defining_classes.contains_key(defining_entity) { - let old_params_offset = input_class_storage - .template_types - .keys() - .position(|x| x == param_name) - .unwrap(); - + if defining_classes.iter().any(|(e, _)| e == defining_entity) { let candidate_param_type_inner = input_type_params .get(old_params_offset) .unwrap_or(&(None, get_mixed_any())) .clone() .1; - mapped_input_offset = - input_class_storage.template_types.get_index_of(param_name); + mapped_input_offset = Some(old_params_offset); candidate_param_type = Some(candidate_param_type_inner); } diff --git a/src/ttype/type_expander.rs b/src/ttype/type_expander.rs index a1e74c4d..57d2b42f 100644 --- a/src/ttype/type_expander.rs +++ b/src/ttype/type_expander.rs @@ -332,9 +332,9 @@ fn expand_atomic( let mut untemplated_type = if let Some(type_params) = type_params { let mut new_template_types = IndexMap::new(); - for (i, (k, v)) in (&type_definition.template_types).into_iter().enumerate() { + for (i, (k, v)) in type_definition.template_types.iter().enumerate() { let mut h = FxHashMap::default(); - for kk in v.keys() { + for (kk, _) in v { h.insert(*kk, type_params.get(i).unwrap().clone()); } @@ -431,9 +431,9 @@ fn expand_atomic( let mut definition_as_type = if let Some(type_params) = type_params { let mut new_template_types = IndexMap::new(); - for (i, (k, v)) in (&type_definition.template_types).into_iter().enumerate() { + for (i, (k, v)) in type_definition.template_types.iter().enumerate() { let mut h = FxHashMap::default(); - for kk in v.keys() { + for (kk, _) in v { h.insert( *kk, if let Some(t) = type_params.get(i) {