@@ -362,6 +362,11 @@ function inferBlock(
362
362
} else if ( terminal . kind === 'maybe-throw' ) {
363
363
const handlerParam = context . catchHandlers . get ( terminal . handler ) ;
364
364
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
+ } ) ;
365
370
const effects : Array < AliasingEffect > = [ ] ;
366
371
for ( const instr of block . instructions ) {
367
372
if (
@@ -476,14 +481,14 @@ function applySignature(
476
481
* Track which values we've already aliased once, so that we can switch to
477
482
* appendAlias() for subsequent aliases into the same value
478
483
*/
479
- const aliased = new Set < IdentifierId > ( ) ;
484
+ const initialized = new Set < IdentifierId > ( ) ;
480
485
481
486
if ( DEBUG ) {
482
487
console . log ( printInstruction ( instruction ) ) ;
483
488
}
484
489
485
490
for ( const effect of signature . effects ) {
486
- applyEffect ( context , state , effect , aliased , effects ) ;
491
+ applyEffect ( context , state , effect , initialized , effects ) ;
487
492
}
488
493
if ( DEBUG ) {
489
494
console . log (
@@ -508,7 +513,7 @@ function applyEffect(
508
513
context : Context ,
509
514
state : InferenceState ,
510
515
_effect : AliasingEffect ,
511
- aliased : Set < IdentifierId > ,
516
+ initialized : Set < IdentifierId > ,
512
517
effects : Array < AliasingEffect > ,
513
518
) : void {
514
519
const effect = context . internEffect ( _effect ) ;
@@ -524,6 +529,13 @@ function applyEffect(
524
529
break ;
525
530
}
526
531
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
+
527
539
let value = context . effectInstructionValueCache . get ( effect ) ;
528
540
if ( value == null ) {
529
541
value = {
@@ -538,6 +550,7 @@ function applyEffect(
538
550
reason : new Set ( [ effect . reason ] ) ,
539
551
} ) ;
540
552
state . define ( effect . into , value ) ;
553
+ effects . push ( effect ) ;
541
554
break ;
542
555
}
543
556
case 'ImmutableCapture' : {
@@ -555,6 +568,13 @@ function applyEffect(
555
568
break ;
556
569
}
557
570
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
+
558
578
const fromValue = state . kind ( effect . from ) ;
559
579
let value = context . effectInstructionValueCache . get ( effect ) ;
560
580
if ( value == null ) {
@@ -573,10 +593,21 @@ function applyEffect(
573
593
switch ( fromValue . kind ) {
574
594
case ValueKind . Primitive :
575
595
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
+ } ) ;
577
602
break ;
578
603
}
579
604
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
+ } ) ;
580
611
applyEffect (
581
612
context ,
582
613
state ,
@@ -585,7 +616,7 @@ function applyEffect(
585
616
from : effect . from ,
586
617
into : effect . into ,
587
618
} ,
588
- aliased ,
619
+ initialized ,
589
620
effects ,
590
621
) ;
591
622
break ;
@@ -597,6 +628,13 @@ function applyEffect(
597
628
break ;
598
629
}
599
630
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
+
600
638
effects . push ( effect ) ;
601
639
/**
602
640
* We consider the function mutable if it has any mutable context variables or
@@ -653,14 +691,22 @@ function applyEffect(
653
691
from : capture ,
654
692
into : effect . into ,
655
693
} ,
656
- aliased ,
694
+ initialized ,
657
695
effects ,
658
696
) ;
659
697
}
660
698
break ;
661
699
}
662
700
case 'Alias' :
663
701
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
+ ) ;
664
710
/*
665
711
* Capture describes potential information flow: storing a pointer to one value
666
712
* within another. If the destination is not mutable, or the source value has
@@ -698,7 +744,7 @@ function applyEffect(
698
744
from : effect . from ,
699
745
into : effect . into ,
700
746
} ,
701
- aliased ,
747
+ initialized ,
702
748
effects ,
703
749
) ;
704
750
break ;
@@ -714,6 +760,13 @@ function applyEffect(
714
760
break ;
715
761
}
716
762
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
+
717
770
/*
718
771
* Alias represents potential pointer aliasing. If the type is a global,
719
772
* a primitive (copy-on-write semantics) then we can prune the effect
@@ -730,7 +783,7 @@ function applyEffect(
730
783
from : effect . from ,
731
784
into : effect . into ,
732
785
} ,
733
- aliased ,
786
+ initialized ,
734
787
effects ,
735
788
) ;
736
789
let value = context . effectInstructionValueCache . get ( effect ) ;
@@ -768,12 +821,7 @@ function applyEffect(
768
821
break ;
769
822
}
770
823
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 ) ;
777
825
effects . push ( effect ) ;
778
826
break ;
779
827
}
@@ -826,11 +874,11 @@ function applyEffect(
826
874
context ,
827
875
state ,
828
876
{ kind : 'MutateTransitiveConditionally' , value : effect . function } ,
829
- aliased ,
877
+ initialized ,
830
878
effects ,
831
879
) ;
832
880
for ( const signatureEffect of signatureEffects ) {
833
- applyEffect ( context , state , signatureEffect , aliased , effects ) ;
881
+ applyEffect ( context , state , signatureEffect , initialized , effects ) ;
834
882
}
835
883
break ;
836
884
}
@@ -858,7 +906,7 @@ function applyEffect(
858
906
console . log ( 'apply aliasing signature effects' ) ;
859
907
}
860
908
for ( const signatureEffect of signatureEffects ) {
861
- applyEffect ( context , state , signatureEffect , aliased , effects ) ;
909
+ applyEffect ( context , state , signatureEffect , initialized , effects ) ;
862
910
}
863
911
} else if ( effect . signature != null ) {
864
912
if ( DEBUG ) {
@@ -873,7 +921,7 @@ function applyEffect(
873
921
effect . loc ,
874
922
) ;
875
923
for ( const legacyEffect of legacyEffects ) {
876
- applyEffect ( context , state , legacyEffect , aliased , effects ) ;
924
+ applyEffect ( context , state , legacyEffect , initialized , effects ) ;
877
925
}
878
926
} else {
879
927
if ( DEBUG ) {
@@ -888,7 +936,7 @@ function applyEffect(
888
936
value : ValueKind . Mutable ,
889
937
reason : ValueReason . Other ,
890
938
} ,
891
- aliased ,
939
+ initialized ,
892
940
effects ,
893
941
) ;
894
942
/*
@@ -911,21 +959,21 @@ function applyEffect(
911
959
kind : 'MutateTransitiveConditionally' ,
912
960
value : operand ,
913
961
} ,
914
- aliased ,
962
+ initialized ,
915
963
effects ,
916
964
) ;
917
965
}
918
966
const mutateIterator =
919
967
arg . kind === 'Spread' ? conditionallyMutateIterator ( operand ) : null ;
920
968
if ( mutateIterator ) {
921
- applyEffect ( context , state , mutateIterator , aliased , effects ) ;
969
+ applyEffect ( context , state , mutateIterator , initialized , effects ) ;
922
970
}
923
971
applyEffect (
924
972
context ,
925
973
state ,
926
974
// OK: recording information flow
927
975
{ kind : 'Alias' , from : operand , into : effect . into } ,
928
- aliased ,
976
+ initialized ,
929
977
effects ,
930
978
) ;
931
979
for ( const otherArg of [
@@ -953,7 +1001,7 @@ function applyEffect(
953
1001
from : operand ,
954
1002
into : other ,
955
1003
} ,
956
- aliased ,
1004
+ initialized ,
957
1005
effects ,
958
1006
) ;
959
1007
}
@@ -1009,7 +1057,7 @@ function applyEffect(
1009
1057
suggestions : null ,
1010
1058
} ,
1011
1059
} ,
1012
- aliased ,
1060
+ initialized ,
1013
1061
effects ,
1014
1062
) ;
1015
1063
}
@@ -1028,7 +1076,7 @@ function applyEffect(
1028
1076
suggestions : null ,
1029
1077
} ,
1030
1078
} ,
1031
- aliased ,
1079
+ initialized ,
1032
1080
effects ,
1033
1081
) ;
1034
1082
} else {
@@ -1059,7 +1107,7 @@ function applyEffect(
1059
1107
suggestions : null ,
1060
1108
} ,
1061
1109
} ,
1062
- aliased ,
1110
+ initialized ,
1063
1111
effects ,
1064
1112
) ;
1065
1113
}
@@ -1166,7 +1214,7 @@ class InferenceState {
1166
1214
}
1167
1215
1168
1216
// 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 {
1170
1218
const values = this . #variables. get ( value . identifier . id ) ;
1171
1219
CompilerError . invariant ( values != null , {
1172
1220
reason : `[InferMutationAliasingEffects] Expected value for identifier to be initialized` ,
0 commit comments