11import { CompilerError } from '../CompilerError' ;
22import { inRange } from '../ReactiveScopes/InferReactiveScopeVariables' ;
3+ import { printDependency } from '../ReactiveScopes/PrintReactiveFunction' ;
34import {
45 Set_equal ,
56 Set_filter ,
@@ -23,6 +24,8 @@ import {
2324} from './HIR' ;
2425import { collectTemporariesSidemap } from './PropagateScopeDependenciesHIR' ;
2526
27+ const DEBUG_PRINT = false ;
28+
2629/**
2730 * Helper function for `PropagateScopeDependencies`. Uses control flow graph
2831 * analysis to determine which `Identifier`s can be assumed to be non-null
@@ -86,15 +89,8 @@ export function collectHoistablePropertyLoads(
8689 fn : HIRFunction ,
8790 temporaries : ReadonlyMap < IdentifierId , ReactiveScopeDependency > ,
8891 hoistableFromOptionals : ReadonlyMap < BlockId , ReactiveScopeDependency > ,
89- nestedFnImmutableContext : ReadonlySet < IdentifierId > | null ,
9092) : ReadonlyMap < BlockId , BlockInfo > {
9193 const registry = new PropertyPathRegistry ( ) ;
92-
93- const functionExpressionLoads = collectFunctionExpressionFakeLoads ( fn ) ;
94- const actuallyEvaluatedTemporaries = new Map (
95- [ ...temporaries ] . filter ( ( [ id ] ) => ! functionExpressionLoads . has ( id ) ) ,
96- ) ;
97-
9894 /**
9995 * Due to current limitations of mutable range inference, there are edge cases in
10096 * which we infer known-immutable values (e.g. props or hook params) to have a
@@ -111,14 +107,51 @@ export function collectHoistablePropertyLoads(
111107 }
112108 }
113109 }
114- const nodes = collectNonNullsInBlocks ( fn , {
115- temporaries : actuallyEvaluatedTemporaries ,
110+ return collectHoistablePropertyLoadsImpl ( fn , {
111+ temporaries,
116112 knownImmutableIdentifiers,
117113 hoistableFromOptionals,
118114 registry,
119- nestedFnImmutableContext,
115+ nestedFnImmutableContext : null ,
120116 } ) ;
121- propagateNonNull ( fn , nodes , registry ) ;
117+ }
118+
119+ type CollectHoistablePropertyLoadsContext = {
120+ temporaries : ReadonlyMap < IdentifierId , ReactiveScopeDependency > ;
121+ knownImmutableIdentifiers : ReadonlySet < IdentifierId > ;
122+ hoistableFromOptionals : ReadonlyMap < BlockId , ReactiveScopeDependency > ;
123+ registry : PropertyPathRegistry ;
124+ /**
125+ * (For nested / inner function declarations)
126+ * Context variables (i.e. captured from an outer scope) that are immutable.
127+ * Note that this technically could be merged into `knownImmutableIdentifiers`,
128+ * but are currently kept separate for readability.
129+ */
130+ nestedFnImmutableContext : ReadonlySet < IdentifierId > | null ;
131+ } ;
132+ function collectHoistablePropertyLoadsImpl (
133+ fn : HIRFunction ,
134+ context : CollectHoistablePropertyLoadsContext ,
135+ ) : ReadonlyMap < BlockId , BlockInfo > {
136+ const functionExpressionLoads = collectFunctionExpressionFakeLoads ( fn ) ;
137+ const actuallyEvaluatedTemporaries = new Map (
138+ [ ...context . temporaries ] . filter ( ( [ id ] ) => ! functionExpressionLoads . has ( id ) ) ,
139+ ) ;
140+
141+ const nodes = collectNonNullsInBlocks ( fn , {
142+ ...context ,
143+ temporaries : actuallyEvaluatedTemporaries ,
144+ } ) ;
145+ propagateNonNull ( fn , nodes , context . registry ) ;
146+
147+ if ( DEBUG_PRINT ) {
148+ console . log ( '(printing hoistable nodes in blocks)' ) ;
149+ for ( const [ blockId , node ] of nodes ) {
150+ console . log (
151+ `bb${ blockId } : ${ [ ...node . assumedNonNullObjects ] . map ( n => printDependency ( n . fullPath ) ) . join ( ' ' ) } ` ,
152+ ) ;
153+ }
154+ }
122155
123156 return nodes ;
124157}
@@ -243,7 +276,7 @@ class PropertyPathRegistry {
243276
244277function getMaybeNonNullInInstruction (
245278 instr : InstructionValue ,
246- context : CollectNonNullsInBlocksContext ,
279+ context : CollectHoistablePropertyLoadsContext ,
247280) : PropertyPathNode | null {
248281 let path = null ;
249282 if ( instr . kind === 'PropertyLoad' ) {
@@ -262,7 +295,7 @@ function getMaybeNonNullInInstruction(
262295function isImmutableAtInstr (
263296 identifier : Identifier ,
264297 instr : InstructionId ,
265- context : CollectNonNullsInBlocksContext ,
298+ context : CollectHoistablePropertyLoadsContext ,
266299) : boolean {
267300 if ( context . nestedFnImmutableContext != null ) {
268301 /**
@@ -295,22 +328,9 @@ function isImmutableAtInstr(
295328 }
296329}
297330
298- type CollectNonNullsInBlocksContext = {
299- temporaries : ReadonlyMap < IdentifierId , ReactiveScopeDependency > ;
300- knownImmutableIdentifiers : ReadonlySet < IdentifierId > ;
301- hoistableFromOptionals : ReadonlyMap < BlockId , ReactiveScopeDependency > ;
302- registry : PropertyPathRegistry ;
303- /**
304- * (For nested / inner function declarations)
305- * Context variables (i.e. captured from an outer scope) that are immutable.
306- * Note that this technically could be merged into `knownImmutableIdentifiers`,
307- * but are currently kept separate for readability.
308- */
309- nestedFnImmutableContext : ReadonlySet < IdentifierId > | null ;
310- } ;
311331function collectNonNullsInBlocks (
312332 fn : HIRFunction ,
313- context : CollectNonNullsInBlocksContext ,
333+ context : CollectHoistablePropertyLoadsContext ,
314334) : ReadonlyMap < BlockId , BlockInfo > {
315335 /**
316336 * Known non-null objects such as functional component props can be safely
@@ -358,18 +378,22 @@ function collectNonNullsInBlocks(
358378 new Set ( ) ,
359379 ) ;
360380 const innerOptionals = collectOptionalChainSidemap ( innerFn . func ) ;
361- const innerHoistableMap = collectHoistablePropertyLoads (
381+ const innerHoistableMap = collectHoistablePropertyLoadsImpl (
362382 innerFn . func ,
363- innerTemporaries ,
364- innerOptionals . hoistableObjects ,
365- context . nestedFnImmutableContext ??
366- new Set (
367- innerFn . func . context
368- . filter ( place =>
369- isImmutableAtInstr ( place . identifier , instr . id , context ) ,
370- )
371- . map ( place => place . identifier . id ) ,
372- ) ,
383+ {
384+ ...context ,
385+ temporaries : innerTemporaries , // TODO: remove in later PR
386+ hoistableFromOptionals : innerOptionals . hoistableObjects , // TODO: remove in later PR
387+ nestedFnImmutableContext :
388+ context . nestedFnImmutableContext ??
389+ new Set (
390+ innerFn . func . context
391+ . filter ( place =>
392+ isImmutableAtInstr ( place . identifier , instr . id , context ) ,
393+ )
394+ . map ( place => place . identifier . id ) ,
395+ ) ,
396+ } ,
373397 ) ;
374398 const innerHoistables = assertNonNull (
375399 innerHoistableMap . get ( innerFn . func . body . entry ) ,
0 commit comments