@@ -558,7 +558,14 @@ let compile_lambda =
558558 (~name=?, id, env, args, body, attrs, loc): Mashtree . closure_data => {
559559 register_function(id);
560560 let (body , return_type ) = body;
561- let used_var_set = Anf_utils . anf_free_vars(body);
561+ // NOTE: we special-case `id`, since we want to
562+ // have simply-recursive uses of identifiers use
563+ // argument 0 ("$self") rather than do the self-reference
564+ // via a closure variable (this enables a large class
565+ // of recursive functions to be garbage-collectible, since
566+ // Grain's garbage collector does not currently collect
567+ // cyclic reference chains)
568+ let used_var_set = Ident . Set . remove(id, Anf_utils . anf_free_vars(body));
562569 let arg_vars = List . map(((arg, _)) => arg, args);
563570 let global_vars =
564571 Ident . fold_all((id, _, acc) => [ id, ... acc] , global_table^, [] );
@@ -587,7 +594,8 @@ let compile_lambda =
587594 },
588595 free_binds,
589596 new_args,
590- );
597+ )
598+ |> Ident . add(id, MArgBind (Int32 . of_int(0 ), Types . HeapAllocated ));
591599 let idx = next_lift() ;
592600 let args = List . map(((_, ty)) => ty, new_args);
593601 let arity = List . length(args);
0 commit comments