13
//! - `src/HIR/DeriveMinimalDependenciesHIR.ts`
14
15
use indexmap::IndexMap;
16
-use std::collections::{BTreeSet, HashMap, HashSet};
16
+use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
17
+use std::collections::BTreeSet;
18
19
use react_compiler_hir::environment::Environment;
20
use react_compiler_hir::visitors::{ScopeBlockInfo, ScopeBlockTraversal};
45
let (working, registry) =
46
collect_hoistable_and_propagate(func, env, &temporaries, &hoistable_objects);
47
// Convert to scope-keyed map with full dependency paths
47
- let mut keyed: HashMap<ScopeId, Vec<ReactiveScopeDependency>> = HashMap::new();
48
+ let mut keyed: FxHashMap<ScopeId, Vec<ReactiveScopeDependency>> = FxHashMap::default();
49
for (_block_id, block) in &func.body.blocks {
50
if let Terminal::Scope {
51
scope,
129
fn find_temporaries_used_outside_declaring_scope(
130
func: &HirFunction,
131
env: &Environment,
131
-) -> HashSet<DeclarationId> {
132
- let mut declarations: HashMap<DeclarationId, ScopeId> = HashMap::new();
133
- let mut pruned_scopes: HashSet<ScopeId> = HashSet::new();
132
+) -> FxHashSet<DeclarationId> {
133
+ let mut declarations: FxHashMap<DeclarationId, ScopeId> = FxHashMap::default();
134
+ let mut pruned_scopes: FxHashSet<ScopeId> = FxHashSet::default();
135
let mut traversal = ScopeBlockTraversal::new();
135
- let mut used_outside_declaring_scope: HashSet<DeclarationId> = HashSet::new();
136
+ let mut used_outside_declaring_scope: FxHashSet<DeclarationId> = FxHashSet::default();
137
138
let handle_place = |place_id: IdentifierId,
138
- declarations: &HashMap<DeclarationId, ScopeId>,
139
+ declarations: &FxHashMap<DeclarationId, ScopeId>,
140
traversal: &ScopeBlockTraversal,
140
- pruned_scopes: &HashSet<ScopeId>,
141
- used_outside: &mut HashSet<DeclarationId>,
141
+ pruned_scopes: &FxHashSet<ScopeId>,
142
+ used_outside: &mut FxHashSet<DeclarationId>,
143
env: &Environment| {
144
let decl_id = env.identifiers[place_id.0 as usize].declaration_id;
145
if let Some(&declaring_scope) = declarations.get(&decl_id) {
228
fn collect_temporaries_sidemap(
229
func: &HirFunction,
230
env: &Environment,
230
- used_outside_declaring_scope: &HashSet<DeclarationId>,
231
-) -> HashMap<IdentifierId, ReactiveScopeDependency> {
232
- let mut temporaries = HashMap::new();
231
+ used_outside_declaring_scope: &FxHashSet<DeclarationId>,
232
+) -> FxHashMap<IdentifierId, ReactiveScopeDependency> {
233
+ let mut temporaries = FxHashMap::default();
234
collect_temporaries_sidemap_impl(
235
func,
236
env,
270
fn collect_temporaries_sidemap_impl(
271
func: &HirFunction,
272
env: &Environment,
272
- used_outside_declaring_scope: &HashSet<DeclarationId>,
273
- temporaries: &mut HashMap<IdentifierId, ReactiveScopeDependency>,
273
+ used_outside_declaring_scope: &FxHashSet<DeclarationId>,
274
+ temporaries: &mut FxHashMap<IdentifierId, ReactiveScopeDependency>,
275
inner_fn_context: Option<EvaluationOrder>,
276
) {
277
for (_block_id, block) in &func.body.blocks {
370
property_name: &PropertyLiteral,
371
optional: bool,
372
loc: Option<react_compiler_hir::SourceLocation>,
372
- temporaries: &HashMap<IdentifierId, ReactiveScopeDependency>,
373
+ temporaries: &FxHashMap<IdentifierId, ReactiveScopeDependency>,
374
_env: &Environment,
375
) -> ReactiveScopeDependency {
376
let resolved = temporaries.get(&object.identifier);
406
// =============================================================================
407
408
struct OptionalChainSidemap {
408
- temporaries_read_in_optional: HashMap<IdentifierId, ReactiveScopeDependency>,
409
- processed_instrs_in_optional: HashSet<ProcessedInstr>,
410
- hoistable_objects: HashMap<BlockId, ReactiveScopeDependency>,
409
+ temporaries_read_in_optional: FxHashMap<IdentifierId, ReactiveScopeDependency>,
410
+ processed_instrs_in_optional: FxHashSet<ProcessedInstr>,
411
+ hoistable_objects: FxHashMap<BlockId, ReactiveScopeDependency>,
412
}
413
414
/// We track processed instructions/terminals by their lvalue IdentifierId + block id.
424
425
fn collect_optional_chain_sidemap(func: &HirFunction, env: &Environment) -> OptionalChainSidemap {
426
let mut ctx = OptionalTraversalContext {
426
- seen_optionals: HashSet::new(),
427
- processed_instrs_in_optional: HashSet::new(),
428
- temporaries_read_in_optional: HashMap::new(),
429
- hoistable_objects: HashMap::new(),
427
+ seen_optionals: FxHashSet::default(),
428
+ processed_instrs_in_optional: FxHashSet::default(),
429
+ temporaries_read_in_optional: FxHashMap::default(),
430
+ hoistable_objects: FxHashMap::default(),
431
};
432
433
traverse_function_optional(func, env, &mut ctx);
440
}
441
442
struct OptionalTraversalContext {
442
- seen_optionals: HashSet<BlockId>,
443
- processed_instrs_in_optional: HashSet<ProcessedInstr>,
444
- temporaries_read_in_optional: HashMap<IdentifierId, ReactiveScopeDependency>,
445
- hoistable_objects: HashMap<BlockId, ReactiveScopeDependency>,
443
+ seen_optionals: FxHashSet<BlockId>,
444
+ processed_instrs_in_optional: FxHashSet<ProcessedInstr>,
445
+ temporaries_read_in_optional: FxHashMap<IdentifierId, ReactiveScopeDependency>,
446
+ hoistable_objects: FxHashMap<BlockId, ReactiveScopeDependency>,
447
}
448
449
fn traverse_function_optional(
786
787
#[derive(Debug, Clone)]
788
struct PropertyPathNode {
788
- properties: HashMap<PropertyLiteral, usize>, // index into registry
789
- optional_properties: HashMap<PropertyLiteral, usize>, // index into registry
789
+ properties: FxHashMap<PropertyLiteral, usize>, // index into registry
790
+ optional_properties: FxHashMap<PropertyLiteral, usize>, // index into registry
791
#[allow(dead_code)]
792
parent: Option<usize>,
793
full_path: ReactiveScopeDependency,
798
799
struct PropertyPathRegistry {
800
nodes: Vec<PropertyPathNode>,
800
- roots: HashMap<IdentifierId, usize>,
801
+ roots: FxHashMap<IdentifierId, usize>,
802
}
803
804
impl PropertyPathRegistry {
805
fn new() -> Self {
806
Self {
807
nodes: Vec::new(),
807
- roots: HashMap::new(),
808
+ roots: FxHashMap::default(),
809
}
810
}
811
820
}
821
let idx = self.nodes.len();
822
self.nodes.push(PropertyPathNode {
822
- properties: HashMap::new(),
823
- optional_properties: HashMap::new(),
823
+ properties: FxHashMap::default(),
824
+ optional_properties: FxHashMap::default(),
825
parent: None,
826
full_path: ReactiveScopeDependency {
827
identifier: identifier_id,
859
let mut new_path = parent_full_path.path.clone();
860
new_path.push(entry.clone());
861
self.nodes.push(PropertyPathNode {
861
- properties: HashMap::new(),
862
- optional_properties: HashMap::new(),
862
+ properties: FxHashMap::default(),
863
+ optional_properties: FxHashMap::default(),
864
parent: Some(parent_idx),
865
full_path: ReactiveScopeDependency {
866
identifier: parent_full_path.identifier,
963
fn collect_hoistable_property_loads(
964
func: &HirFunction,
965
env: &Environment,
965
- temporaries: &HashMap<IdentifierId, ReactiveScopeDependency>,
966
- hoistable_from_optionals: &HashMap<BlockId, ReactiveScopeDependency>,
967
-) -> HashMap<BlockId, BlockInfo> {
966
+ temporaries: &FxHashMap<IdentifierId, ReactiveScopeDependency>,
967
+ hoistable_from_optionals: &FxHashMap<BlockId, ReactiveScopeDependency>,
968
+) -> FxHashMap<BlockId, BlockInfo> {
969
let mut registry = PropertyPathRegistry::new();
969
- let known_immutable_identifiers: HashSet<IdentifierId> = if func.fn_type
970
+ let known_immutable_identifiers: FxHashSet<IdentifierId> = if func.fn_type
971
== ReactFunctionType::Component
972
|| func.fn_type == ReactFunctionType::Hook
973
{
979
})
980
.collect()
981
} else {
981
- HashSet::new()
982
+ FxHashSet::default()
983
};
984
985
let assumed_invoked_fns = get_assumed_invoked_functions(func, env);
995
}
996
997
struct CollectHoistableContext<'a> {
997
- temporaries: &'a HashMap<IdentifierId, ReactiveScopeDependency>,
998
- known_immutable_identifiers: &'a HashSet<IdentifierId>,
999
- hoistable_from_optionals: &'a HashMap<BlockId, ReactiveScopeDependency>,
1000
- nested_fn_immutable_context: Option<&'a HashSet<IdentifierId>>,
1001
- assumed_invoked_fns: &'a HashSet<FunctionId>,
998
+ temporaries: &'a FxHashMap<IdentifierId, ReactiveScopeDependency>,
999
+ known_immutable_identifiers: &'a FxHashSet<IdentifierId>,
1000
+ hoistable_from_optionals: &'a FxHashMap<BlockId, ReactiveScopeDependency>,
1001
+ nested_fn_immutable_context: Option<&'a FxHashSet<IdentifierId>>,
1002
+ assumed_invoked_fns: &'a FxHashSet<FunctionId>,
1003
}
1004
1005
fn is_immutable_at_instr(
1028
1029
fn get_maybe_non_null_in_instruction(
1030
value: &InstructionValue,
1030
- temporaries: &HashMap<IdentifierId, ReactiveScopeDependency>,
1031
+ temporaries: &FxHashMap<IdentifierId, ReactiveScopeDependency>,
1032
) -> Option<ReactiveScopeDependency> {
1033
match value {
1034
InstructionValue::PropertyLoad { object, .. } => Some(
1058
env: &Environment,
1059
ctx: &CollectHoistableContext,
1060
registry: &mut PropertyPathRegistry,
1060
-) -> HashMap<BlockId, BlockInfo> {
1061
+) -> FxHashMap<BlockId, BlockInfo> {
1062
let nodes = collect_non_nulls_in_blocks(func, env, ctx, registry);
1063
let working = propagate_non_null(func, &nodes, registry);
1063
- // Return the propagated results, converting HashSet<usize> back to BlockInfo
1064
+ // Return the propagated results, converting FxHashSet<usize> back to BlockInfo
1065
working
1066
.into_iter()
1067
.map(|(k, v)| {
1079
/// Returns the set of LoweredFunction FunctionIds that are assumed to be invoked.
1080
/// The `temporaries` map is shared across recursive calls (matching TS behavior where
1081
/// the same Map is passed to recursive invocations for inner functions).
1081
-fn get_assumed_invoked_functions(func: &HirFunction, env: &Environment) -> HashSet<FunctionId> {
1082
- let mut temporaries: HashMap<IdentifierId, (FunctionId, HashSet<FunctionId>)> = HashMap::new();
1082
+fn get_assumed_invoked_functions(func: &HirFunction, env: &Environment) -> FxHashSet<FunctionId> {
1083
+ let mut temporaries: FxHashMap<IdentifierId, (FunctionId, FxHashSet<FunctionId>)> =
1084
+ FxHashMap::default();
1085
get_assumed_invoked_functions_impl(func, env, &mut temporaries)
1086
}
1087
1088
fn get_assumed_invoked_functions_impl(
1089
func: &HirFunction,
1090
env: &Environment,
1089
- temporaries: &mut HashMap<IdentifierId, (FunctionId, HashSet<FunctionId>)>,
1090
-) -> HashSet<FunctionId> {
1091
- let mut hoistable: HashSet<FunctionId> = HashSet::new();
1091
+ temporaries: &mut FxHashMap<IdentifierId, (FunctionId, FxHashSet<FunctionId>)>,
1092
+) -> FxHashSet<FunctionId> {
1093
+ let mut hoistable: FxHashSet<FunctionId> = FxHashSet::default();
1094
1095
// Step 1: Collect identifier to function expression mappings
1096
for (_block_id, block) in &func.body.blocks {
1098
let instr = &func.instructions[instr_id.0 as usize];
1099
match &instr.value {
1100
InstructionValue::FunctionExpression { lowered_func, .. } => {
1099
- temporaries
1100
- .insert(instr.lvalue.identifier, (lowered_func.func, HashSet::new()));
1101
+ temporaries.insert(
1102
+ instr.lvalue.identifier,
1103
+ (lowered_func.func, FxHashSet::default()),
1104
+ );
1105
}
1106
InstructionValue::StoreLocal {
1107
value: val, lvalue, ..
1225
env: &Environment,
1226
ctx: &CollectHoistableContext,
1227
registry: &mut PropertyPathRegistry,
1224
-) -> HashMap<BlockId, BlockInfo> {
1228
+) -> FxHashMap<BlockId, BlockInfo> {
1229
// Known non-null identifiers (e.g. component props)
1230
let mut known_non_null: BTreeSet<usize> = BTreeSet::new();
1231
if func.fn_type == ReactFunctionType::Component && !func.params.is_empty() {
1235
}
1236
}
1237
1234
- let mut nodes: HashMap<BlockId, BlockInfo> = HashMap::new();
1238
+ let mut nodes: FxHashMap<BlockId, BlockInfo> = FxHashMap::default();
1239
1240
for (block_id, block) in &func.body.blocks {
1241
let mut assumed = known_non_null.clone();
1294
if ctx.assumed_invoked_fns.contains(&lowered_func.func) {
1295
let inner_func = &env.functions[lowered_func.func.0 as usize];
1296
// Build nested fn immutable context
1293
- let nested_fn_immutable_context: HashSet<IdentifierId> =
1297
+ let nested_fn_immutable_context: FxHashSet<IdentifierId> =
1298
if ctx.nested_fn_immutable_context.is_some() {
1299
// Already in a nested fn context, use existing
1300
ctx.nested_fn_immutable_context.unwrap().clone()
1311
let inner_assumed = get_assumed_invoked_functions(inner_func, env);
1312
let inner_ctx = CollectHoistableContext {
1313
temporaries: ctx.temporaries,
1310
- known_immutable_identifiers: &HashSet::new(),
1314
+ known_immutable_identifiers: &FxHashSet::default(),
1315
hoistable_from_optionals: ctx.hoistable_from_optionals,
1316
nested_fn_immutable_context: Some(&nested_fn_immutable_context),
1317
assumed_invoked_fns: &inner_assumed,
1351
/// and should be filtered out, allowing non-null info to propagate through non-cyclic paths.
1352
fn propagate_non_null(
1353
func: &HirFunction,
1350
- nodes: &HashMap<BlockId, BlockInfo>,
1354
+ nodes: &FxHashMap<BlockId, BlockInfo>,
1355
registry: &mut PropertyPathRegistry,
1352
-) -> HashMap<BlockId, BTreeSet<usize>> {
1356
+) -> FxHashMap<BlockId, BTreeSet<usize>> {
1357
// Build successor map. Use BTreeSet to iterate successors in sorted BlockId
1358
// order, matching the TS Set<BlockId> insertion order (blocks are created in
1359
// ascending BlockId order).
1356
- let mut block_successors: HashMap<BlockId, BTreeSet<BlockId>> = HashMap::new();
1360
+ let mut block_successors: FxHashMap<BlockId, BTreeSet<BlockId>> = FxHashMap::default();
1361
for (block_id, block) in &func.body.blocks {
1362
for pred in &block.preds {
1363
block_successors.entry(*pred).or_default().insert(*block_id);
1365
}
1366
1367
// Clone nodes into mutable working set
1364
- let mut working: HashMap<BlockId, BTreeSet<usize>> = nodes
1368
+ let mut working: FxHashMap<BlockId, BTreeSet<usize>> = nodes
1369
.iter()
1370
.map(|(k, v)| (*k, v.assumed_non_null_objects.clone()))
1371
.collect();
1378
let mut changed = false;
1379
1380
// Forward pass (using predecessors)
1377
- let mut traversal_state: HashMap<BlockId, TraversalState> = HashMap::new();
1381
+ let mut traversal_state: FxHashMap<BlockId, TraversalState> = FxHashMap::default();
1382
for &block_id in &block_ids {
1383
let block_changed = recursively_propagate_non_null(
1384
block_id,
1430
fn recursively_propagate_non_null(
1431
node_id: BlockId,
1432
direction: PropagationDirection,
1429
- traversal_state: &mut HashMap<BlockId, TraversalState>,
1430
- working: &mut HashMap<BlockId, BTreeSet<usize>>,
1433
+ traversal_state: &mut FxHashMap<BlockId, TraversalState>,
1434
+ working: &mut FxHashMap<BlockId, BTreeSet<usize>>,
1435
func: &HirFunction,
1432
- block_successors: &HashMap<BlockId, BTreeSet<BlockId>>,
1436
+ block_successors: &FxHashMap<BlockId, BTreeSet<BlockId>>,
1437
registry: &mut PropertyPathRegistry,
1438
) -> bool {
1439
// Avoid re-visiting computed or currently active nodes
1504
fn collect_hoistable_and_propagate(
1505
func: &HirFunction,
1506
env: &Environment,
1503
- temporaries: &HashMap<IdentifierId, ReactiveScopeDependency>,
1504
- hoistable_from_optionals: &HashMap<BlockId, ReactiveScopeDependency>,
1505
-) -> (HashMap<BlockId, BTreeSet<usize>>, PropertyPathRegistry) {
1507
+ temporaries: &FxHashMap<IdentifierId, ReactiveScopeDependency>,
1508
+ hoistable_from_optionals: &FxHashMap<BlockId, ReactiveScopeDependency>,
1509
+) -> (FxHashMap<BlockId, BTreeSet<usize>>, PropertyPathRegistry) {
1510
let mut registry = PropertyPathRegistry::new();
1511
let assumed_invoked_fns = get_assumed_invoked_functions(func, env);
1508
- let known_immutable_identifiers: HashSet<IdentifierId> = if func.fn_type
1512
+ let known_immutable_identifiers: FxHashSet<IdentifierId> = if func.fn_type
1513
== ReactFunctionType::Component
1514
|| func.fn_type == ReactFunctionType::Hook
1515
{
1521
})
1522
.collect()
1523
} else {
1520
- HashSet::new()
1524
+ FxHashSet::default()
1525
};
1526
1527
let ctx = CollectHoistableContext {
1542
#[allow(dead_code)]
1543
fn key_by_scope_id(
1544
func: &HirFunction,
1541
- block_keyed: &HashMap<BlockId, BlockInfo>,
1542
-) -> HashMap<ScopeId, BlockInfo> {
1543
- let mut keyed: HashMap<ScopeId, BlockInfo> = HashMap::new();
1545
+ block_keyed: &FxHashMap<BlockId, BlockInfo>,
1546
+) -> FxHashMap<ScopeId, BlockInfo> {
1547
+ let mut keyed: FxHashMap<ScopeId, BlockInfo> = FxHashMap::default();
1548
for (_block_id, block) in &func.body.blocks {
1549
if let Terminal::Scope {
1550
scope,
1604
}
1605
1606
struct HoistableNode {
1603
- properties: HashMap<PropertyLiteral, Box<HoistableNodeEntry>>,
1607
+ properties: FxHashMap<PropertyLiteral, Box<HoistableNodeEntry>>,
1608
access_type: HoistableAccessType,
1609
}
1610
1613
}
1614
1615
struct DependencyNode {
1612
- properties: IndexMap<PropertyLiteral, Box<DependencyNodeEntry>>,
1616
+ properties: IndexMap<PropertyLiteral, Box<DependencyNodeEntry>, FxBuildHasher>,
1617
access_type: PropertyAccessType,
1618
loc: Option<react_compiler_hir::SourceLocation>,
1619
}
1623
}
1624
1625
struct ReactiveScopeDependencyTreeHIR {
1622
- hoistable_roots: HashMap<IdentifierId, (HoistableNode, bool)>, // node + reactive
1623
- dep_roots: IndexMap<IdentifierId, (DependencyNode, bool)>, // node + reactive (preserves insertion order like JS Map)
1626
+ hoistable_roots: FxHashMap<IdentifierId, (HoistableNode, bool)>, // node + reactive
1627
+ dep_roots: IndexMap<IdentifierId, (DependencyNode, bool), FxBuildHasher>, // node + reactive (preserves insertion order like JS Map)
1628
}
1629
1630
impl ReactiveScopeDependencyTreeHIR {
1632
hoistable_objects: impl Iterator<Item = &'a ReactiveScopeDependency>,
1633
_env: &Environment,
1634
) -> Self {
1631
- let mut hoistable_roots: HashMap<IdentifierId, (HoistableNode, bool)> = HashMap::new();
1635
+ let mut hoistable_roots: FxHashMap<IdentifierId, (HoistableNode, bool)> =
1636
+ FxHashMap::default();
1637
1638
// Sort hoistable objects so that entries with optional first path come
1639
// before non-optional ones. This matches the TS behavior where
1656
};
1657
(
1658
HoistableNode {
1654
- properties: HashMap::new(),
1659
+ properties: FxHashMap::default(),
1660
access_type,
1661
},
1662
dep.reactive,
1676
.or_insert_with(|| {
1677
Box::new(HoistableNodeEntry {
1678
node: HoistableNode {
1674
- properties: HashMap::new(),
1679
+ properties: FxHashMap::default(),
1680
access_type,
1681
},
1682
})
1687
1688
Self {
1689
hoistable_roots,
1685
- dep_roots: IndexMap::new(),
1690
+ dep_roots: IndexMap::default(),
1691
}
1692
}
1693
1695
let root = self.dep_roots.entry(dep.identifier).or_insert_with(|| {
1696
(
1697
DependencyNode {
1693
- properties: IndexMap::new(),
1698
+ properties: IndexMap::default(),
1699
access_type: PropertyAccessType::UnconditionalAccess,
1700
loc: dep.loc,
1701
},
1740
.or_insert_with(|| {
1741
Box::new(DependencyNodeEntry {
1742
node: DependencyNode {
1738
- properties: IndexMap::new(),
1743
+ properties: IndexMap::default(),
1744
access_type,
1745
loc: entry.loc,
1746
},
1814
1815
/// Context for dependency collection.
1816
struct DependencyCollectionContext<'a> {
1812
- declarations: HashMap<DeclarationId, Decl>,
1813
- reassignments: HashMap<IdentifierId, Decl>,
1817
+ declarations: FxHashMap<DeclarationId, Decl>,
1818
+ reassignments: FxHashMap<IdentifierId, Decl>,
1819
scope_stack: Vec<ScopeId>,
1820
dep_stack: Vec<Vec<ReactiveScopeDependency>>,
1816
- deps: IndexMap<ScopeId, Vec<ReactiveScopeDependency>>,
1817
- temporaries: &'a HashMap<IdentifierId, ReactiveScopeDependency>,
1821
+ deps: IndexMap<ScopeId, Vec<ReactiveScopeDependency>, FxBuildHasher>,
1822
+ temporaries: &'a FxHashMap<IdentifierId, ReactiveScopeDependency>,
1823
#[allow(dead_code)]
1819
- temporaries_used_outside_scope: &'a HashSet<DeclarationId>,
1820
- processed_instrs_in_optional: &'a HashSet<ProcessedInstr>,
1824
+ temporaries_used_outside_scope: &'a FxHashSet<DeclarationId>,
1825
+ processed_instrs_in_optional: &'a FxHashSet<ProcessedInstr>,
1826
inner_fn_context: Option<EvaluationOrder>,
1827
}
1828
1829
impl<'a> DependencyCollectionContext<'a> {
1830
fn new(
1826
- temporaries_used_outside_scope: &'a HashSet<DeclarationId>,
1827
- temporaries: &'a HashMap<IdentifierId, ReactiveScopeDependency>,
1828
- processed_instrs_in_optional: &'a HashSet<ProcessedInstr>,
1831
+ temporaries_used_outside_scope: &'a FxHashSet<DeclarationId>,
1832
+ temporaries: &'a FxHashMap<IdentifierId, ReactiveScopeDependency>,
1833
+ processed_instrs_in_optional: &'a FxHashSet<ProcessedInstr>,
1834
) -> Self {
1835
Self {
1831
- declarations: HashMap::new(),
1832
- reassignments: HashMap::new(),
1836
+ declarations: FxHashMap::default(),
1837
+ reassignments: FxHashMap::default(),
1838
scope_stack: Vec::new(),
1839
dep_stack: Vec::new(),
1835
- deps: IndexMap::new(),
1840
+ deps: IndexMap::default(),
1841
temporaries,
1842
temporaries_used_outside_scope,
1843
processed_instrs_in_optional,
2227
fn collect_dependencies(
2228
func: &HirFunction,
2229
env: &mut Environment,
2225
- used_outside_declaring_scope: &HashSet<DeclarationId>,
2226
- temporaries: &HashMap<IdentifierId, ReactiveScopeDependency>,
2227
- processed_instrs_in_optional: &HashSet<ProcessedInstr>,
2228
-) -> IndexMap<ScopeId, Vec<ReactiveScopeDependency>> {
2230
+ used_outside_declaring_scope: &FxHashSet<DeclarationId>,
2231
+ temporaries: &FxHashMap<IdentifierId, ReactiveScopeDependency>,
2232
+ processed_instrs_in_optional: &FxHashSet<ProcessedInstr>,
2233
+) -> IndexMap<ScopeId, Vec<ReactiveScopeDependency>, FxBuildHasher> {
2234
let mut ctx = DependencyCollectionContext::new(
2235
used_outside_declaring_scope,
2236
temporaries,