Generic struct with generic member function signature has strange behavior

Hi,

First time here…
I found an interesting “feature” and I am not sure if it is bug or if I am missing something. I am using the 0.13.0 version of zig.

Here is the code:

const std = @import("std");

fn CreateTuple(comptime len: u8) type {
    return struct {
        const Self = @This();

        fn init() Self { return .{};}

        fn addUp(tuple: [len]u32) u32 {
            var sum: u32 = 0;
            for (tuple) |item| {
                sum += item;
            }
            return sum;
        }
    };
}

pub fn main() !void {
    // const MyTuple = CreateTuple(2).init();
    const MyTuple = CreateTuple(2);
    std.debug.print("Sum is {}", .{ MyTuple.addUp(.{2, 2})  });
}

This works as expected, but if I uncomment the first line in main(), the compiler complains that ‘addUp’ is not a member function of CreateTuple(2). Calling init() should not change anything in my opinion.

Calling init does not change anything.

Also:

  • init does not return a type but an instance of a type
  • addUp is not a method (instance function where the first argument have type Self) but a function namespaced by the type.
3 Likes

I’d like to add an example to emphasize @dimdin’s point.

Think about it like ArrayList. Array list has an init function that belongs to the class. It does not belong to an instance of the class.

var list = ArrayList(u8).init(allocator);

// This will fail because init doesn't belong to an instance
_ = list.init(allocator);

In your case, when you call init, you return an instance. You’d have to modify the addUp function to include a self: Self parameter to make it work with an instance.

3 Likes