Open
Description
Currently, @src()
returns source it's own location, even in inline functions:
const std = @import("std");
inline
fn f(a: std.builtin.SourceLocation) void {
const b = @src();
inline for (.{ a, b }, .{ "a", "b" }) |location, name| {
std.debug.print("{s} = {s}:{}:{}\n", .{
name,
location.file,
location.line,
location.column,
});
}
}
pub fn main() void {
f(@src());
}
a = main.zig:16:7
b = main.zig:4:15
Given that inline
functions are inlined semantically, it is theoretically possible to also provide SourceLocation
of the call-site. There are several ways to handle this:
- Just change
@src()
to always be caller's location in an inline function - Provide
@callerSrc()
which is a syntax error if called outside ofinline fn
- Add
caller: ?*SourceLocation
field tostd.builtin.SourceLocation
which is non-null iff@src()
is inside a function. This allows for having several levels of ancestral@src()
if an inline function calls another inline function. - Maybe something else?
If implemented, this feature could enable several patterns. For example, there's a Rust GUI framework that uses equivalent feature to implement Flutter-like memorization: https://github.com/anp/moxie/blob/4f71b6f28340b2db263f07d0883394fa0b233de0/topo/src/lib.rs#L140-L192
Specific use-case I am interested in is this:
pub inline fn assert(condition: bool) {
const src = @callerSrc();
if (!condition) {
std.debug.panic("assertion failure: {s}:{}:{}", .{src.file, src.line, src.column})
}
}
That is, I want to write an assert
function which prints the location of the failure even if the code is compiled with Release, and all debug info is stripped.