Need help to debug sample code with 'inline else'. Getting a cast error

Hi,

I’m new to Zig world, and trying to learn it via master’s language reference. Using 0.11.0-dev.4282+0f21d3d4d linux x86-64 compiler.

I’m in “switch” section, and was writing a sample code with “inline else”. My error is of expected type though, am guessing I missed something simple… would appreciate help.

I’m posting sample code and error below. :pray:

const std = @import("std");
const debugPrint = std.debug.print;

pub fn main() !void {
    switch_inline_else();
}

fn switch_inline_else() void {
    const Cat = struct {
        const Self = @This();
        pub fn talk(self: *Self) void {
            debugPrint("{s} says Meow~\n", .{self.name});
        }

        name: []const u8,
    };
    const Dog = struct {
        const Self = @This();
        pub fn talk(self: *Self) void {
            debugPrint("{s} says Bark~\n", .{self.name});
        }

        name: []const u8,
    };

    const Animal = union(enum) {
        const Self = @This();
        pub fn talk(self: *Self) void {
            switch (self.*) {
                inline else => |case| case.talk(),
            }
        }

        cat: Cat,
        dog: Dog,
    };
    var dartDog: Dog = .{ .name = "Dart" };
    var dart: Animal = .{ .dog = dartDog };
    debugPrint("{any}\n", .{dart});
    dart.talk();
}

gives error of

/tmp/a.zig:30:43: error: expected type '*a.switch_inline_else.Cat', found '*const a.switch_inline_else.Cat'
                inline else => |case| case.talk(),
                                      ~~~~^~~~~
/tmp/a.zig:30:43: note: cast discards const qualifier
/tmp/a.zig:11:27: note: parameter type declared here
        pub fn talk(self: *Self) void {
                          ^~~~~
referenced by:
    switch_inline_else: /tmp/a.zig:40:9
    main: /tmp/a.zig:5:5

Edit.1: Also, any other notes on the code are appreciated as well.

You are capturing case by value:

inline else => |case| case.talk(),

This is creating a local, constant copy.
You can solve this by capturing by reference instead:

inline else => |*case| case.talk(),

I would however recommend a different approach:
The talk function is not changing the input pointer, so there is no need to pass a mutable pointer here:

pub fn talk(self: Self) void { // Note: Don't forget to change all instances

This might even bring performance improvements since now the compiler is allowed to decide whether pass-by-value or pass-by-reference should be preferred.

2 Likes

@IntegratedQuantum thanks, |*case| capture be reference works.

I’ve also changed *Self to Self. I wrongly assumed, reference got passed to type’s functions.

1 Like