Skip to content

Commit cfed01f

Browse files
authored
Turn off transformation for closures inside loops (#6480)
The scope of `var` is per-function, requiring a transformation for closures inside loops when capturing loop variables. This PR turns off the transformation.
1 parent 7bf97d9 commit cfed01f

30 files changed

+150
-398
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
- Fix indent for returned/thrown/wrapped in parentheses objects in generated js code. https://github.com/rescript-lang/rescript-compiler/pull/6746
3333
- Fix indent in generated js code. https://github.com/rescript-lang/rescript-compiler/pull/6747
3434
- In generated code, use `let` instead of `var`. https://github.com/rescript-lang/rescript-compiler/pull/6102
35+
- Turn off transformation for closures inside loops when capturing loop variables, now that `let` is emitted instead of `var`. https://github.com/rescript-lang/rescript-compiler/pull/6480
3536

3637
# 11.1.0
3738

jscomp/core/j.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,14 @@ and statement_desc =
254254
(* Function declaration and Variable declaration *)
255255
| Exp of expression
256256
| If of expression * block * block
257-
| While of label option * expression * block * Js_closure.t
257+
| While of label option * expression * block
258258
(* check if it contains loop mutable values, happens in nested loop *)
259259
| ForRange of
260260
for_ident_expression option
261261
* finish_ident_expression
262262
* for_ident
263263
* for_direction
264264
* block
265-
* Js_closure.t
266265
| Continue of label
267266
| Break (* only used when inline a fucntion *)
268267
| Return of expression

jscomp/core/js_closure.ml

Lines changed: 0 additions & 31 deletions
This file was deleted.

jscomp/core/js_closure.mli

Lines changed: 0 additions & 35 deletions
This file was deleted.

jscomp/core/js_dump.ml

Lines changed: 8 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,6 @@ let exp_need_paren (e : J.expression) =
164164
| Await _ -> false
165165
| Tagged_template _ -> false
166166

167-
let comma_idents (cxt : cxt) f ls = iter_lst cxt f ls Ext_pp_scope.ident comma
168-
169-
let pp_paren_params (inner_cxt : cxt) (f : Ext_pp.t) (lexical : Ident.t list) :
170-
unit =
171-
P.string f L.lparen;
172-
let (_ : cxt) = comma_idents inner_cxt f lexical in
173-
P.string f L.rparen
174-
175167
(** Print as underscore for unused vars, may not be
176168
needed in the future *)
177169
(* let ipp_ident cxt f id (un_used : bool) =
@@ -381,10 +373,9 @@ and pp_function ~return_unit ~async ~is_method cxt (f : P.t) ~fn_state
381373
P.space f;
382374
P.brace_vgroup f 1 (fun _ -> function_body ~return_unit cxt f b)
383375
in
384-
let lexical : Set_ident.t = Js_fun_env.get_lexical_scope env in
385-
let enclose lexical =
386-
let handle lexical =
387-
if Set_ident.is_empty lexical then (
376+
let enclose () =
377+
let handle () =
378+
(
388379
match fn_state with
389380
| Is_return ->
390381
return_sp f;
@@ -408,46 +399,10 @@ and pp_function ~return_unit ~async ~is_method cxt (f : P.t) ~fn_state
408399
P.space f;
409400
ignore (Ext_pp_scope.ident inner_cxt f x : cxt);
410401
param_body ())
411-
else
412-
(* print our closure as
413-
{[(function(x,y){ return function(..){...}} (x,y))]}
414-
Maybe changed to `let` in the future
415-
*)
416-
let lexical = Set_ident.elements lexical in
417-
(match fn_state with
418-
| Is_return -> return_sp f
419-
| No_name _ -> ()
420-
| Name_non_top name | Name_top name ->
421-
ignore (pp_var_assign inner_cxt f name : cxt));
422-
if async then P.string f L.await;
423-
P.string f L.lparen;
424-
P.string f (L.function_async ~async);
425-
pp_paren_params inner_cxt f lexical;
426-
P.brace_vgroup f 0 (fun _ ->
427-
return_sp f;
428-
P.string f (L.function_async ~async);
429-
P.space f;
430-
(match fn_state with
431-
| Is_return | No_name _ -> ()
432-
| Name_non_top x | Name_top x ->
433-
ignore (Ext_pp_scope.ident inner_cxt f x));
434-
param_body ());
435-
pp_paren_params inner_cxt f lexical;
436-
P.string f L.rparen;
437-
match fn_state with
438-
| Is_return | No_name _ -> () (* expression *)
439-
| _ -> semi f
440-
(* has binding, a statement *)
441402
in
442-
handle
443-
(match fn_state with
444-
| (Name_top name | Name_non_top name) when Set_ident.mem lexical name
445-
->
446-
(*TODO: when calculating lexical we should not include itself *)
447-
Set_ident.remove lexical name
448-
| _ -> lexical)
403+
handle ()
449404
in
450-
enclose lexical;
405+
enclose ();
451406
outer_cxt
452407

453408
(* Assume the cond would not change the context,
@@ -1065,7 +1020,7 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
10651020
P.string f L.else_;
10661021
P.space f;
10671022
brace_block cxt f s2)
1068-
| While (label, e, s, _env) ->
1023+
| While (label, e, s) ->
10691024
(* FIXME: print scope as well *)
10701025
(match label with
10711026
| Some i ->
@@ -1093,7 +1048,7 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
10931048
let cxt = brace_block cxt f s in
10941049
semi f;
10951050
cxt
1096-
| ForRange (for_ident_expression, finish, id, direction, s, env) ->
1051+
| ForRange (for_ident_expression, finish, id, direction, s) ->
10971052
let action cxt =
10981053
P.vgroup f 0 (fun _ ->
10991054
let cxt =
@@ -1164,24 +1119,7 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
11641119
in
11651120
brace_block cxt f s)
11661121
in
1167-
let lexical = Js_closure.get_lexical_scope env in
1168-
if Set_ident.is_empty lexical then action cxt
1169-
else
1170-
(* unlike function,
1171-
[print for loop] has side effect,
1172-
we should take it out
1173-
*)
1174-
let inner_cxt = Ext_pp_scope.merge cxt lexical in
1175-
let lexical = Set_ident.elements lexical in
1176-
P.vgroup f 0 (fun _ ->
1177-
P.string f L.lparen;
1178-
P.string f L.function_;
1179-
pp_paren_params inner_cxt f lexical;
1180-
let cxt = P.brace_vgroup f 0 (fun _ -> action inner_cxt) in
1181-
pp_paren_params inner_cxt f lexical;
1182-
P.string f L.rparen;
1183-
semi f;
1184-
cxt)
1122+
action cxt
11851123
| Continue s ->
11861124
continue f s;
11871125
cxt

jscomp/core/js_fold.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,12 @@ class fold =
217217
let _self = _self#block _x1 in
218218
let _self = _self#block _x2 in
219219
_self
220-
| While (_x0, _x1, _x2, _x3) ->
220+
| While (_x0, _x1, _x2) ->
221221
let _self = option (fun _self -> _self#label) _self _x0 in
222222
let _self = _self#expression _x1 in
223223
let _self = _self#block _x2 in
224224
_self
225-
| ForRange (_x0, _x1, _x2, _x3, _x4, _x5) ->
225+
| ForRange (_x0, _x1, _x2, _x3, _x4) ->
226226
let _self =
227227
option (fun _self -> _self#for_ident_expression) _self _x0
228228
in

jscomp/core/js_fun_env.ml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ type immutable_mask =
4444

4545
type t = {
4646
mutable unbounded : Set_ident.t;
47-
mutable bound_loop_mutable_values : Set_ident.t;
4847
used_mask : bool array;
4948
immutable_mask : immutable_mask;
5049
}
@@ -58,7 +57,6 @@ let make ?immutable_mask n =
5857
(match immutable_mask with
5958
| Some x -> Immutable_mask x
6059
| None -> All_immutable_and_no_tail_call);
61-
bound_loop_mutable_values = Set_ident.empty;
6260
}
6361

6462
let no_tailcall x =
@@ -92,13 +90,3 @@ let set_unbounded env v =
9290
(* if Set_ident.is_empty env.bound then *)
9391
env.unbounded <- v
9492
(* else assert false *)
95-
96-
let set_lexical_scope env bound_loop_mutable_values =
97-
env.bound_loop_mutable_values <- bound_loop_mutable_values
98-
99-
let get_lexical_scope env = env.bound_loop_mutable_values
100-
101-
(* TODO: can be refined if it
102-
only enclose toplevel variables
103-
*)
104-
(* let is_empty t = Set_ident.is_empty t.unbounded *)

jscomp/core/js_fun_env.mli

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ val no_tailcall : t -> bool list
3636

3737
val set_unbounded : t -> Set_ident.t -> unit
3838

39-
val set_lexical_scope : t -> Set_ident.t -> unit
40-
41-
val get_lexical_scope : t -> Set_ident.t
42-
4339
(* val to_string : t -> string *)
4440

4541
val mark_unused : t -> int -> unit

jscomp/core/js_pass_scope.ml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,6 @@ let record_scope_pass =
173173
due to the recursive thing
174174
*)
175175
Js_fun_env.set_unbounded env closured_idents';
176-
let lexical_scopes =
177-
Set_ident.(inter closured_idents' state.loop_mutable_values)
178-
in
179-
Js_fun_env.set_lexical_scope env lexical_scopes;
180176
(* tailcall , note that these varibles are used in another pass *)
181177
{
182178
state with
@@ -242,7 +238,7 @@ let record_scope_pass =
242238
statement =
243239
(fun self state x ->
244240
match x.statement_desc with
245-
| ForRange (_, _, loop_id, _, _, a_env) ->
241+
| ForRange (_, _, loop_id, _, _) ->
246242
(* TODO: simplify definition of For *)
247243
let {
248244
defined_idents = defined_idents';
@@ -274,8 +270,6 @@ let record_scope_pass =
274270
(diff closured_idents' defined_idents')
275271
state.loop_mutable_values)
276272
in
277-
let () = Js_closure.set_lexical_scope a_env lexical_scope in
278-
(* set scope *)
279273
{
280274
state with
281275
used_idents = Set_ident.union state.used_idents used_idents';
@@ -293,7 +287,7 @@ let record_scope_pass =
293287
closured_idents =
294288
Set_ident.union state.closured_idents lexical_scope;
295289
}
296-
| While (_label, pred, body, _env) ->
290+
| While (_label, pred, body) ->
297291
with_in_loop
298292
(self.block self
299293
(with_in_loop (self.expression self state pred) true)

jscomp/core/js_record_fold.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,12 @@ let statement_desc : 'a. ('a, statement_desc) fn =
223223
let st = _self.block _self st _x1 in
224224
let st = _self.block _self st _x2 in
225225
st
226-
| While (_x0, _x1, _x2, _x3) ->
226+
| While (_x0, _x1, _x2) ->
227227
let st = option label _self st _x0 in
228228
let st = _self.expression _self st _x1 in
229229
let st = _self.block _self st _x2 in
230230
st
231-
| ForRange (_x0, _x1, _x2, _x3, _x4, _x5) ->
231+
| ForRange (_x0, _x1, _x2, _x3, _x4) ->
232232
let st = option for_ident_expression _self st _x0 in
233233
let st = finish_ident_expression _self st _x1 in
234234
let st = _self.for_ident _self st _x2 in

0 commit comments

Comments
 (0)