@@ -362,6 +362,11 @@ function inferBlock(
362362 } else if ( terminal . kind === 'maybe-throw' ) {
363363 const handlerParam = context . catchHandlers . get ( terminal . handler ) ;
364364 if ( handlerParam != null ) {
365+ CompilerError . invariant ( state . kind ( handlerParam ) != null , {
366+ reason :
367+ 'Expected catch binding to be intialized with a DeclareLocal Catch instruction' ,
368+ loc : terminal . loc ,
369+ } ) ;
365370 const effects : Array < AliasingEffect > = [ ] ;
366371 for ( const instr of block . instructions ) {
367372 if (
@@ -476,14 +481,14 @@ function applySignature(
476481 * Track which values we've already aliased once, so that we can switch to
477482 * appendAlias() for subsequent aliases into the same value
478483 */
479- const aliased = new Set < IdentifierId > ( ) ;
484+ const initialized = new Set < IdentifierId > ( ) ;
480485
481486 if ( DEBUG ) {
482487 console . log ( printInstruction ( instruction ) ) ;
483488 }
484489
485490 for ( const effect of signature . effects ) {
486- applyEffect ( context , state , effect , aliased , effects ) ;
491+ applyEffect ( context , state , effect , initialized , effects ) ;
487492 }
488493 if ( DEBUG ) {
489494 console . log (
@@ -508,7 +513,7 @@ function applyEffect(
508513 context : Context ,
509514 state : InferenceState ,
510515 _effect : AliasingEffect ,
511- aliased : Set < IdentifierId > ,
516+ initialized : Set < IdentifierId > ,
512517 effects : Array < AliasingEffect > ,
513518) : void {
514519 const effect = context . internEffect ( _effect ) ;
@@ -524,6 +529,13 @@ function applyEffect(
524529 break ;
525530 }
526531 case 'Create' : {
532+ CompilerError . invariant ( ! initialized . has ( effect . into . identifier . id ) , {
533+ reason : `Cannot re-initialize variable within an instruction` ,
534+ description : `Re-initialized ${ printPlace ( effect . into ) } in ${ printAliasingEffect ( effect ) } ` ,
535+ loc : effect . into . loc ,
536+ } ) ;
537+ initialized . add ( effect . into . identifier . id ) ;
538+
527539 let value = context . effectInstructionValueCache . get ( effect ) ;
528540 if ( value == null ) {
529541 value = {
@@ -538,6 +550,7 @@ function applyEffect(
538550 reason : new Set ( [ effect . reason ] ) ,
539551 } ) ;
540552 state . define ( effect . into , value ) ;
553+ effects . push ( effect ) ;
541554 break ;
542555 }
543556 case 'ImmutableCapture' : {
@@ -555,6 +568,13 @@ function applyEffect(
555568 break ;
556569 }
557570 case 'CreateFrom' : {
571+ CompilerError . invariant ( ! initialized . has ( effect . into . identifier . id ) , {
572+ reason : `Cannot re-initialize variable within an instruction` ,
573+ description : `Re-initialized ${ printPlace ( effect . into ) } in ${ printAliasingEffect ( effect ) } ` ,
574+ loc : effect . into . loc ,
575+ } ) ;
576+ initialized . add ( effect . into . identifier . id ) ;
577+
558578 const fromValue = state . kind ( effect . from ) ;
559579 let value = context . effectInstructionValueCache . get ( effect ) ;
560580 if ( value == null ) {
@@ -573,10 +593,21 @@ function applyEffect(
573593 switch ( fromValue . kind ) {
574594 case ValueKind . Primitive :
575595 case ValueKind . Global : {
576- // no need to track this data flow
596+ effects . push ( {
597+ kind : 'Create' ,
598+ value : fromValue . kind ,
599+ into : effect . into ,
600+ reason : [ ...fromValue . reason ] [ 0 ] ?? ValueReason . Other ,
601+ } ) ;
577602 break ;
578603 }
579604 case ValueKind . Frozen : {
605+ effects . push ( {
606+ kind : 'Create' ,
607+ value : fromValue . kind ,
608+ into : effect . into ,
609+ reason : [ ...fromValue . reason ] [ 0 ] ?? ValueReason . Other ,
610+ } ) ;
580611 applyEffect (
581612 context ,
582613 state ,
@@ -585,7 +616,7 @@ function applyEffect(
585616 from : effect . from ,
586617 into : effect . into ,
587618 } ,
588- aliased ,
619+ initialized ,
589620 effects ,
590621 ) ;
591622 break ;
@@ -597,6 +628,13 @@ function applyEffect(
597628 break ;
598629 }
599630 case 'CreateFunction' : {
631+ CompilerError . invariant ( ! initialized . has ( effect . into . identifier . id ) , {
632+ reason : `Cannot re-initialize variable within an instruction` ,
633+ description : `Re-initialized ${ printPlace ( effect . into ) } in ${ printAliasingEffect ( effect ) } ` ,
634+ loc : effect . into . loc ,
635+ } ) ;
636+ initialized . add ( effect . into . identifier . id ) ;
637+
600638 effects . push ( effect ) ;
601639 /**
602640 * We consider the function mutable if it has any mutable context variables or
@@ -653,14 +691,22 @@ function applyEffect(
653691 from : capture ,
654692 into : effect . into ,
655693 } ,
656- aliased ,
694+ initialized ,
657695 effects ,
658696 ) ;
659697 }
660698 break ;
661699 }
662700 case 'Alias' :
663701 case 'Capture' : {
702+ CompilerError . invariant (
703+ effect . kind === 'Capture' || initialized . has ( effect . into . identifier . id ) ,
704+ {
705+ reason : `Expected destination value to already be initialized within this instruction for Alias effect` ,
706+ description : `Destination ${ printPlace ( effect . into ) } is not initialized in this instruction` ,
707+ loc : effect . into . loc ,
708+ } ,
709+ ) ;
664710 /*
665711 * Capture describes potential information flow: storing a pointer to one value
666712 * within another. If the destination is not mutable, or the source value has
@@ -698,7 +744,7 @@ function applyEffect(
698744 from : effect . from ,
699745 into : effect . into ,
700746 } ,
701- aliased ,
747+ initialized ,
702748 effects ,
703749 ) ;
704750 break ;
@@ -714,6 +760,13 @@ function applyEffect(
714760 break ;
715761 }
716762 case 'Assign' : {
763+ CompilerError . invariant ( ! initialized . has ( effect . into . identifier . id ) , {
764+ reason : `Cannot re-initialize variable within an instruction` ,
765+ description : `Re-initialized ${ printPlace ( effect . into ) } in ${ printAliasingEffect ( effect ) } ` ,
766+ loc : effect . into . loc ,
767+ } ) ;
768+ initialized . add ( effect . into . identifier . id ) ;
769+
717770 /*
718771 * Alias represents potential pointer aliasing. If the type is a global,
719772 * a primitive (copy-on-write semantics) then we can prune the effect
@@ -730,7 +783,7 @@ function applyEffect(
730783 from : effect . from ,
731784 into : effect . into ,
732785 } ,
733- aliased ,
786+ initialized ,
734787 effects ,
735788 ) ;
736789 let value = context . effectInstructionValueCache . get ( effect ) ;
@@ -768,12 +821,7 @@ function applyEffect(
768821 break ;
769822 }
770823 default : {
771- if ( aliased . has ( effect . into . identifier . id ) ) {
772- state . appendAlias ( effect . into , effect . from ) ;
773- } else {
774- aliased . add ( effect . into . identifier . id ) ;
775- state . alias ( effect . into , effect . from ) ;
776- }
824+ state . assign ( effect . into , effect . from ) ;
777825 effects . push ( effect ) ;
778826 break ;
779827 }
@@ -826,11 +874,11 @@ function applyEffect(
826874 context ,
827875 state ,
828876 { kind : 'MutateTransitiveConditionally' , value : effect . function } ,
829- aliased ,
877+ initialized ,
830878 effects ,
831879 ) ;
832880 for ( const signatureEffect of signatureEffects ) {
833- applyEffect ( context , state , signatureEffect , aliased , effects ) ;
881+ applyEffect ( context , state , signatureEffect , initialized , effects ) ;
834882 }
835883 break ;
836884 }
@@ -858,7 +906,7 @@ function applyEffect(
858906 console . log ( 'apply aliasing signature effects' ) ;
859907 }
860908 for ( const signatureEffect of signatureEffects ) {
861- applyEffect ( context , state , signatureEffect , aliased , effects ) ;
909+ applyEffect ( context , state , signatureEffect , initialized , effects ) ;
862910 }
863911 } else if ( effect . signature != null ) {
864912 if ( DEBUG ) {
@@ -873,7 +921,7 @@ function applyEffect(
873921 effect . loc ,
874922 ) ;
875923 for ( const legacyEffect of legacyEffects ) {
876- applyEffect ( context , state , legacyEffect , aliased , effects ) ;
924+ applyEffect ( context , state , legacyEffect , initialized , effects ) ;
877925 }
878926 } else {
879927 if ( DEBUG ) {
@@ -888,7 +936,7 @@ function applyEffect(
888936 value : ValueKind . Mutable ,
889937 reason : ValueReason . Other ,
890938 } ,
891- aliased ,
939+ initialized ,
892940 effects ,
893941 ) ;
894942 /*
@@ -911,21 +959,21 @@ function applyEffect(
911959 kind : 'MutateTransitiveConditionally' ,
912960 value : operand ,
913961 } ,
914- aliased ,
962+ initialized ,
915963 effects ,
916964 ) ;
917965 }
918966 const mutateIterator =
919967 arg . kind === 'Spread' ? conditionallyMutateIterator ( operand ) : null ;
920968 if ( mutateIterator ) {
921- applyEffect ( context , state , mutateIterator , aliased , effects ) ;
969+ applyEffect ( context , state , mutateIterator , initialized , effects ) ;
922970 }
923971 applyEffect (
924972 context ,
925973 state ,
926974 // OK: recording information flow
927975 { kind : 'Alias' , from : operand , into : effect . into } ,
928- aliased ,
976+ initialized ,
929977 effects ,
930978 ) ;
931979 for ( const otherArg of [
@@ -953,7 +1001,7 @@ function applyEffect(
9531001 from : operand ,
9541002 into : other ,
9551003 } ,
956- aliased ,
1004+ initialized ,
9571005 effects ,
9581006 ) ;
9591007 }
@@ -1009,7 +1057,7 @@ function applyEffect(
10091057 suggestions : null ,
10101058 } ,
10111059 } ,
1012- aliased ,
1060+ initialized ,
10131061 effects ,
10141062 ) ;
10151063 }
@@ -1028,7 +1076,7 @@ function applyEffect(
10281076 suggestions : null ,
10291077 } ,
10301078 } ,
1031- aliased ,
1079+ initialized ,
10321080 effects ,
10331081 ) ;
10341082 } else {
@@ -1059,7 +1107,7 @@ function applyEffect(
10591107 suggestions : null ,
10601108 } ,
10611109 } ,
1062- aliased ,
1110+ initialized ,
10631111 effects ,
10641112 ) ;
10651113 }
@@ -1166,7 +1214,7 @@ class InferenceState {
11661214 }
11671215
11681216 // Updates the value at @param place to point to the same value as @param value.
1169- alias ( place : Place , value : Place ) : void {
1217+ assign ( place : Place , value : Place ) : void {
11701218 const values = this . #variables. get ( value . identifier . id ) ;
11711219 CompilerError . invariant ( values != null , {
11721220 reason : `[InferMutationAliasingEffects] Expected value for identifier to be initialized` ,
0 commit comments