The following code fails to compile now, because the @panic call causes control flow is diverted error at compile time. But isn’t the call a run-time expression?
var x = "abc";
pub fn main() void {
const T = @TypeOf( @panic(x) );
@import("std").debug.print("{}\n", .{ T });
}
It’s cuz the return type of @panic() is noreturn. The compiler knows that you’re unconditionally calling a noreturn function, so it knows by extension that control flow will never, ever reach past that function call.
But the @TypeOf function treats comptime and runtime code differently. If its argument is comptime, the argument will be evaluated; however if the argument is runtime, then only the type of the argument matters and the runtime argument will be ignored totally at runtime.
Ooh, this is an example of why they’re looking at that ‘_: |T| = @panic(x)’ syntax! It’s totally unambiguous in the new syntax that @panic is going to run, but we kind of expect @TypeOf() to skip it. (Not 100% sure that’s approved as is but the discussion was interesting.)
I like the |T| proposal, but I also like the convenience of the current @TypeOf function in many situations.
If @TypeOf is kept later, I do hope it treats comptime and runtime arguments the same: just cares about their types and never evaluated them, either at run time or compile time.
I’m fine with losing @TypeOf() if I get the unambiguous one, but I kind of see where you’re coming from. Do you have a more real-world example than this @panic example?
Huh, I’ve always used @typeInfo on the type of the function - not the call but the function body or function pointer. I’m not sure if using it on a function call result just never occurred to me or if I misread some bug in past years as not supporting it.
Anyway, end result is I’m already using it in ways that don’t have any possible runtime ambiguity, maybe that’s why I like it better.
True. I think my pattern of creating types w groups of functions works around that part so it’s another way I didn’t realize I was working around a problem.
Er, the description “if the argument of a @TypeOf function call is comptime known, it will get evaluated” is not precise. For example, the while(true) {} loop in the following code is not get executed, but the x += 1; before it gets executed.
The @TypeOf function is really special.
pub fn main() void {
comptime var x: u8 = 0;
const T = @TypeOf({x += 1; while(true) {}});
x += 1;
@import("std").debug.print("{}, {}\n", .{ x, T }); // 2 noreturn
}
It seems the compiler treats {x += 1; while(true) {}} as partially runtime and partially comptime.
This is some weird. So maybe it is a good idea to never evaluate the arguments of @TypeOf calls, for simplicity and fewer subtleties.