Description
Consider this code:
const assert = @import("std").debug.assert;
comptime {
var a: i32 = 1;
const b = &a;
@compileLog(@typeOf(b));
*b = 2;
assert(a == 2);
}
This works fine. The value printed from the @compileLog
statement is &i32
. This makes sense because b
is a pointer to a
.
Now let's do it with a type
:
const assert = @import("std").debug.assert;
comptime {
var a: type = i32;
const b = &a;
@compileLog(b);
*b = f32;
assert(a == f32);
}
$ ./zig build-obj test.zig
| &i32
/home/andy/dev/zig/build/test.zig:6:5: error: found compile log statement
@compileLog(b);
^
/home/andy/dev/zig/build/test.zig:7:5: error: attempt to dereference non-pointer type 'type'
*b = f32;
^
It doesn't work, because the &
operator works differently for type
than other types. Here, b
is a pointer to i32
instead of &type
which is how we wanted to use it.
This prevents other things from working too; for example if you had a []type{i32, u8, f64}
and you tried to use a for
loop, it crashes the compiler because internally a for loop uses the &
operator on the array element.
This is a design flaw in zig; we can't have it both ways.
The only reasonable way I can think of to fix this so far is to introduce a new operator, so we don't have this double-purposed &
. For example:
^x
would be a pointer to typex
.&x
would be taking the address ofx
.
I'm inclined to leave &
as the address-of operator because that is the same as C. Using &
as the pointer-to- operator is already different than C, so it's less cost to people learning the language to change it.