Zig: Private methods can be called on structs using dot syntax

Created on 17 May 2019  路  5Comments  路  Source: ziglang/zig

I cannot call private methods included from another file using "fully qualified" syntax, but I can call them using "dot" syntax, even though they are private:

foo.zig:

pub const Foo = struct {
    fn private(self: Foo) void {
        @compileError("shouldn't be able to call this");
    }
};

main.zig:

const Foo = @import("foo.zig").Foo;

pub fn main() void {
    const foo = Foo{};
    Foo.private(foo); // Cannot call the method like this
    foo.private(); // Can call the method using dot syntax, even though it is private
}

zig build-exe main.zig:

/home/heidezomp/Code/foo/main.zig:5:8: error: 'private' is private
    Foo.private(foo);
       ^
/home/heidezomp/Code/foo/foo.zig:2:5: note: declared here
    fn private(self: Foo) void {
    ^
/home/heidezomp/Code/foo/foo.zig:3:9: error: shouldn't be able to call this
        @compileError("shouldn't be able to call this");
        ^
bug stage1

Most helpful comment

Regarding the calling convention, I dont think Struct.method(instance) is allowed in Zig, but someone more experienced could correct me !

Quoting the documentation:

    // Other than being available to call with dot syntax, struct methods are
    // not special. You can reference them as any other declaration inside
    // the struct:
    assert(Vec3.dot(v1, v2) == 0.0);

All 5 comments

There is no part in the documentation (v0.4.0) that mentions a way to define private methods.
However, this looks like you just created a method called private, that's why it's perfectly fine to call in within your main function.

Regarding the calling convention, I dont think Struct.method(instance) is allowed in Zig, but someone more experienced could correct me !

Regarding the calling convention, I dont think Struct.method(instance) is allowed in Zig, but someone more experienced could correct me !

Quoting the documentation:

    // Other than being available to call with dot syntax, struct methods are
    // not special. You can reference them as any other declaration inside
    // the struct:
    assert(Vec3.dot(v1, v2) == 0.0);

Solved in master branch:

/home/andy/dev/zig/build/test.zig:5:8: error: 'private' is private
    Foo.private(foo); // Cannot call the method like this
       ^
/home/andy/dev/zig/build/foo.zig:2:5: note: declared here
    fn private(self: Foo) void {
    ^

and there is test coverage:

https://github.com/ziglang/zig/blob/c30106c90665079f525129e344cc1c13e4db162b/test/compile_errors.zig#L4743-L4760

This is awesome, thank you so much! :heart: This will make me feel much better about designing nice abstractions.

No sorry @andrewrk, this doesn't seem to be fixed (I am using the master branch). The test case you linked calls the method on the struct, not on an instance of the struct.

The case I am talking about would be expressed as a test case as follows:

 cases.addCase(x: { 
     const tc = cases.create("multiple files with private function error", 
         \\const foo = @import("foo.zig",); 
         \\ 
         \\export fn callPrivFunction() void { 
         \\    const foo_instance = foo.Foo{}; 
         \\    foo_instance.privateFunction();
         \\} 
     , &[_][]const u8{ 
         "tmp.zig:5:17: error: 'privateFunction' is private", 
         "foo.zig:1:1: note: declared here", 
     }); 

     tc.addSourceFile("foo.zig", 
         \\pub const Foo = struct { fn privateFunction(self: Foo) void { } };
     ); 

     break :x tc; 
 }); 

Here foo_instance.privateFunction() should give a compile error, but doesn't.

Was this page helpful?
0 / 5 - 0 ratings