How to use errdefer

I thought it would print “errdefer” but it didn’t
am I misunderstanding how errdefer works?

const std = @import("std");
fn compareRandom(rng: std.rand.Random, comp: i64) !i64 {
    const Error = error{TestError};
    var randomNum = rng.intRangeAtMost(i64, 1, 2);
    if (randomNum < comp) {
        return randomNum;
    } else {
        return Error.TestError;
    }
}
fn returnError(rng: std.rand.Random) !i64 {
    var num = try compareRandom(rng, 0);
    errdefer std.log.info("errdefer", .{});
    return num;
}
pub fn main() !void {
    const rngSeed = @intCast(u64, std.time.timestamp());
    const rng = std.rand.DefaultPrng.init(rngSeed).random();
    _ = returnError(rng) catch |err| {
        std.log.info("{s}", .{err});
    };
}
❯ zig build run
info: error.TestError
1 Like

I thought it would print “errdefer” but it didn’t
am I misunderstanding how errdefer works?

var num = try compareRandom(rng, 0);
errdefer std.log.info("errdefer", .{});

You need to errdefer before possible error return.

3 Likes

My apologies for reviving this, but as a newbie I have been staring at this answer for some time and still don’t get it. Isn’t that errdefer already before the return?

I have a similar test and have compared it to several examples and just cannot see the issue. Can anyone explain this in more detail?

TIA

No, the return is the try on the line before the errdefer.

Remember that try <expression> is syntactic sugar for <expression> catch |e| return e, so every try expression is also a return expression.

4 Likes

@neurocyte Thank you. Makes sense now.

I read that more like “what is the point of the errdefer if there is only a return directly after it?”.

Considering there is no way to trigger an error after the errdefer was executed it seems useless, because there is nothing to trigger it.

So shouldn’t the code be this instead:

fn returnError(rng: std.rand.Random) !i64 {
    errdefer std.log.info("errdefer", .{});
    return try compareRandom(rng, 0);
}

This raises an interesting question: shouldn’t a load-bearing errdefer without any possible error-returning paths be a compile error? It’s unreachable code.

Load-bearing meaning it’s not errdefer comptime unreachable or errdefer unreachable.

4 Likes

Oh right, I knew that sounded familiar (#2654).

3 Likes