In my learning of zig in a few utility projects, I’ve often run into compile errors that only reference zig standard library code. This means there is no clue about what caused it, and I’ve had to effectively bisect my source code by commenting out all recent changes until the error doesn’t occur, then enabling code sometimes line-by-line to figure out what the heck I did wrong. (This is not a new experience, it reminds me of my earliest days learning to program, so there is some nostalgic benefit to the experience. But I expect it will get tiresome soon.)
As a result, I pretty much do C-x C-p c RET as frequently as possible to run tests when I’m writing new code, because I don’t want to get too far down the line before hitting one of these.
I’ve learned so far that it’s nearly always something having to do with a deinit
function I’m doing wrong. For example, I think one of them was an alloc.free(self)
, trying to deallocate something that’s actually on the stack.
So my question is whether there is an issue or tag that tracks these? I’d be happy to contribute tests to demonstrate these patterns as I run into them.
Unclear error message when passing wrong type to allocator.free · Issue #14492 · ziglang/zig · GitHub might be a related issue.
Also relevant is the commit Revert "std: check types of pointers passed to allocator functions" · ziglang/zig@3c2a43f · GitHub which suggests the following enhancement
One thing that might be useful would be having the compiler be aware of
module boundaries and highlighting the boundaries of them. The first
reference note after crossing a module boundary is likely the most
interesting one.
but I can’t find a tracking issue for that idea specifically (outside of being vaguely related to the issue I linked).
As for why you’re getting compile errors originating from within the standard library, it’s most often not because the standard library contains broken code but rather because your code passed something unexpected to a function with an anytype
parameter. (Other situations include calling a function with a comptime
parameter, or an calling an inline function).
For example, std.mem.Allocator.free
has the signature fn (self: Allocator, memory: anytype) void
, but the code expects a slice (you are supposed to use std.mem.Allocator.destroy
to free individual items), so if you pass a single-item pointer, you might get a compile error with a reference trace originating from lib/std/meta.zig
. This might seem odd but it is technically correct since anytype
is duck-typed and that particular line nested within several function calls is the first time some particular constraint is violated.
If you don’t see a reference trace pointing back to one of your own files, you could try adding the -freference-trace
option to your zig build-exe
/zig build
invocation to show all reference traces in full, where you will hopefully find one of your own source files (if you don’t, it might mean there’s a genuine bug in std and/or the compiler).
3 Likes
The issue you mentioned with free()
seems like an easy fix with some simple type info checks. Would that be worth a PR you think?
It looks like that was done and then reverted since it is just a bandaid to the larger issue.
1 Like
Thanks for pointing that out. Looks like there’s more to it than I thought.