这是indexloc提供的服务,不要输入任何密码
Skip to content

Captured environment lost in the recursive call #1299

@Minnerlas

Description

@Minnerlas

I have the following code

(defn testrec [n]
  (let [loop (fn [i]
                   (if (< i n)
                     (loop (+ i 1))
                     i))]
    (loop 0)))

(defn main []
  (IO.println &(fmt "out %d" (testrec 10))))

and I get the following C code for the testrec function

int testrec(int n) {
    int _31;
    /* let */ {
        // This lambda captures 1 variables: n
        _Lambda_testrec_26_env_ty *_26_env = CARP_MALLOC(sizeof(_Lambda_testrec_26_env_ty));
        _26_env->n = n;
        Lambda _26 = {
          .callback = (void*)_Lambda_testrec_26_env,
          .env = _26_env,
          .delete = (void*)_Lambda_testrec_26_env_ty_delete,
          .copy = (void*)_Lambda_testrec_26_env_ty_copy
        };
        Lambda loop = _26;
        int _30 = loop.env ? ((int(*)(LambdaEnv, int))loop.callback)(loop.env, 0) : ((int(*)(int))loop.callback)(0);
        _31 = _30;
        Function_delete__int_int(loop);
    }
    return _31;
}

The environment is clearly stored in the _26 which is passed to the function when it's called

This is the generated function for loop

int _Lambda_testrec_26_env(_Lambda_testrec_26_env_ty* _env, int i) {
    int _25;
    bool _13 = Int__LT_(i, _env->n);
    if (_13) {
        Lambda _15 = { .callback = (void*)_Lambda_testrec_26_env, .env = NULL, .delete = NULL, .copy = NULL }; //Sym_Lambda_testrec_26_env LookupRecursive
        int _19 = Int__PLUS_(i, 1);
        int _20 = _15.env ? ((int(*)(LambdaEnv, int))_15.callback)(_15.env, _19) : ((int(*)(int))_15.callback)(_19);
        int _21 = _20;
        _25 = _21;
    } else {
        int _24 = i;
        _25 = _24;
    }
    return _25;
}

For some reason the .env is never set and the _env is not passed to the next recursive call to loop (_Lambda_testrec_26_env),
but it tries to access _env->n in the next iteration, which is now set to NULL. This causes a segfault and the program crashes.

When i manually set .env = _env in the C code for the lambda, the program works as intended.
This looks like a compiler bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions