Good overview on Rust error handling.
I like errors that are unique and trivially greppable in a codebase. They should be stack efficient and word sized. Maybe a new calling convention where a register is reserved for error code and another register is a pointer to the source location string that is stored in a data segment.
The FP fanboy side of me likes the idea of algebraic effects and ADTs but not at the expense of stack efficiency.
You basically want a modern errno. I don't mean that as a dig at you -- I've found POSIX error codes to still be the best way to design errors in C. If it can't be evaluated by switch, then it's too complicated.