Skip to content

[BUG] drop method called on returned variable #275

@davidscholberg

Description

@davidscholberg

Describe the bug

When you return a variable of a type that implements Drop, the drop method is called on the variable.

To Reproduce

Run the following program:

struct Mover {
    val: int;
}

impl Drop for Mover {
    fn drop(self) {
        println "dropping self.val = {self.val}";
    }
}

fn get_mover(val: int) -> Mover {
    let m = Mover { val: val };
    return m;
}

fn main() {
    let m = get_mover(10);
    println "m.val = {m.val}";
}

The output indicates that the drop method is called twice:

dropping self.val = 0
m.val = 10
dropping self.val = 10

The C version of the get_mover function shows that drop is called on the returned value:

Mover get_mover(int32_t val)
{
    {
        int __z_drop_flag_m = 1;
        Mover m = (struct Mover){.val = val};

        return ({
            ZC_AUTO _z_ret_mv = m;
            memset(&m, 0, sizeof(_z_ret_mv));
            if (__z_drop_flag_m)
                Mover__Drop_glue(&m);
            _z_ret_mv;
        });

        if (__z_drop_flag_m)
            Mover__Drop_glue(&m);
    }
}

Also side note: there's unreachable code after the return statement. Not particularly relevant to this issue but worth pointing out nonetheless.

Expected behavior

I would expect the variable in get_mover to be returned directly with no call to drop, something along the lines of:

Mover get_mover(int32_t val)
{
    {
        Mover m = (struct Mover){.val = val};
        return m;
    }
}

Environment (please complete the following information):

  • OS: Ubuntu 25.04
  • Zen C Version: e4605ce
  • Compiler: gcc (Ubuntu 14.2.0-19ubuntu2) 14.2.0

Additional context

Issue #274 is tangentially related to this due to extraneous code (i.e. temp var copy and memset call) being generated for a variable move.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions