@@ -1010,6 +1010,46 @@ class DeforestTransformer(using val d: Deforest, elabState: Elaborator.State) ex
1010
1010
// If all the arms end with non-`End` blocks, then the `rest` of this `Match` will never be executed,
1011
1011
// and we remove the `rest` in this case. This prevents `rest` to use variables that become
1012
1012
// undefined because computation in arms that defines them are moved away.
1013
+ // One example illustrating the case of "deadcode using never assigned variable causing scope error during JS generation" is as follows:
1014
+ // The mlscript program is:
1015
+ // ```
1016
+ // fun test(x) =
1017
+ // let t = if x is
1018
+ // AA(AA(a)) then a
1019
+ // t + 5
1020
+ // fun f(a) = if a is
1021
+ // AA then 0
1022
+ // let p = AA(AA(10))
1023
+ // test(p) + f(p)
1024
+ // ```
1025
+ // After lowering, it is essentially:
1026
+ // ```
1027
+ // fun test(x) =
1028
+ // if x is AA(param0) then
1029
+ // if param0 is AA(param1) then
1030
+ // a = param1
1031
+ // tmpRes = a
1032
+ // else throw "match error"
1033
+ // else throw "match error"
1034
+ // t = tmpRes
1035
+ // return t + 5
1036
+ // fun f(a) = if a is AA then 0
1037
+ // let p = AA(AA(10))
1038
+ // test(p) + f(p)
1039
+ // ```
1040
+ // And after fusion, the program (before the removal of dead code causing scope error) is:
1041
+ // ```
1042
+ // fun test(x) =
1043
+ // if x is AA(param0) then
1044
+ // param0()
1045
+ // else throw "match error"
1046
+ // t = tmpRes // <--- this `tmpRes` without binding site causes scope error
1047
+ // return t + 5
1048
+ // fun f(a) = if a is AA then 0
1049
+ // let p = AA of
1050
+ // () => a = 10; tmpRes = a; t = tmpRes; return t + 5;
1051
+ // test(p) + f(p)
1052
+ // ```
1013
1053
// TODO: it will become unnecessary once we have proper binding declarations in the Block IR
1014
1054
// and all uses of never-assigned variables will be known to be dead code
1015
1055
dflt.fold(false )(_.willBeNonEndTailBlock) && arms.forall { case (_, body) => body.willBeNonEndTailBlock }
0 commit comments