Comptime reflection on namespaces?

Consider this:

const foobar = struct{
    const foo = @import("foo"); 
    const bar = @import("bar");
};

@compileLog(@typeInfo(foobar));
@compileLog(comptime std.meta.declarations(foobar));

error: found compile log statement

Compile Log Output:
@as(builtin.Type, .{ .@"struct" = .{ .layout = .auto, .backing_integer = null, .fields = &.{}[0..0], .decls = &.{}[0..0], .is_tuple = false } })
@as([]const builtin.Type.Declaration, &.{}[0..0])

Why don’t imported modules show up anywhere in the type information?

Make declarations pub and they’ll show up

3 Likes

@typeInfo only returns pub declarations. This is the case even if called from the same file as the struct declaration, where non-pub would otherwise be accessible.

1 Like

… it seems obvious in hindsight. Thank you. :slight_smile:

For reference:

const foobar = struct{
    pub const foo = @import("foo"); 
    pub const bar = @import("bar");
};

works.

BTW: I never thought of this construction!
It can help to avoid local var / parameter nameclashes.

const using = struct
{
    const board = @import("board.zig");
};

const Board = using.board.Board;

// now I can use "board" as variable / parameter name

For what it’s worth, you can mostly avoid running into this problem if you follow the convention of making imported types into filestructs instead:

Instead of

// in 'board.zig' top level
pub const Board = struct {
    width: f32, 
    height: f32, 
    has_hole: bool,
};

do this

// in 'Board.zig' top level
pub const Board = @This();
width: f32,
height: f32,
has_hole: bool,

then when you import it, import it directly as the type

const Board = @import("Board.zig"); // this equivalent to the old "board.Board"

// "board" now free to be a variable name
const board = Board.init(1.23, 4.56, false);

Thanks. Yes very true. Coming from other languages I am not used yet to “a file is a struct”.
edit: on the other side I like types to have uppercase names and files lowercase :slight_smile:

on the other side I like types to have uppercase names and files lowercase

I agree. I do this:

const Board = @import("board.zig");

The Zig compiler doesn’t though, so I wouldn’t consider it canonical.

I think sticking to PascalCase on filenames that represents structs is a very useful convention.

That is a possibility yes.
In any case: I like the nameclash shadow problem solution!

I do agree, but I would rather not depend on file properties that aren’t universally semantic or supported. Same reason I don’t use spaces in filenames even though that is perfectly valid too.

It’s just casing, and std already does it anyway

Maybe offtopic but anyway:
What happens if I define a const array in consts.zig

VALUES: [256]u8 = ....

and refer to it in someotherfile.zig
with

const consts = @import("consts.zig");
const VALUES = consts.VALUES;

Suddenly I was wondering if I do not have a local copy!!

It’s not that obvious. Prior to version 0.11.0 all declarations were listed and there’s an is_pub field in Declaration.

1 Like

It is a copy (using @intFromPtr)

140702043666519 // address of original
140702043666744 // address of referenced

HOWEVER: in release mode the addresses are the same :slight_smile:

140696585111110
140696585111110
1 Like

Due to constant folding by the optimizer

In hindsight it is, indeed, obvious. But I think that every newcomer to Zig trips over this one. Should be part of FAQ.

File-structs cannot be used with tagged unions or generic functions. If you think about it, it’s rather anti-pattern because it limits free evolution of the codebase (and/or easy refactors).

2 Likes