fix: initialize the error-channel slot on every failable implicit success return (issue 0190)
A failable function that returned by IMPLICIT success (no explicit
`return`) left its error-tag slot uninitialized, so a caller's `catch` /
`or` (or `main`) read a garbage tag and reported a phantom unhandled
error — and for value-carrying failables the success value was dropped.
The "no error" sentinel was only written on the explicit-`return;` path.
Unified all function-body-return lowering so the failable-success slot
is always written:
- void `-> !` fall-through: `ensureTerminator` (control_flow.zig) now
emits `ret constInt(0)` for a pure-failable end-of-body.
- value-failable trailing-expression success: `lowerValueBody`
(stmt.zig) routes through `lowerFailableSuccessReturn`.
- generic + pack-fn instances: `monomorphizeFunction` (generic.zig) and
`monomorphizePackFn` (pack.zig) now DELEGATE their body-return to
`lowerValueBody` instead of hand-rolling a `coerce`+`ret` that drifted
(covers generic/pack value-failables).
Also fixes the missing-value diagnostic guard added here: it now counts
`.err`-level diagnostics (new `DiagnosticList.errorCount`) rather than the
total list length, so a warning/note emitted while lowering the body
(e.g. an ObjC selector arity warning) can no longer suppress a genuine
"body produces no value" error — which previously shipped an
uninitialized return at exit 0.
Regressions: examples/errors/1061 (void fall-through), 1062 (value-failable
trailing expr), 1063 (generic value-failable trailing expr).
This commit is contained in:
@@ -239,6 +239,17 @@ pub const DiagnosticList = struct {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Count of `.err`-level diagnostics (excludes warnings / notes / help).
|
||||
/// Used to detect whether a NEW error was reported across a span of work,
|
||||
/// without a warning/note bumping the total `items` length.
|
||||
pub fn errorCount(self: *const DiagnosticList) usize {
|
||||
var n: usize = 0;
|
||||
for (self.items.items) |d| {
|
||||
if (d.level == .err) n += 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
fn resolveSourceAndFile(self: *const DiagnosticList, d: Diagnostic) struct { source: []const u8, file_name: []const u8 } {
|
||||
if (d.source_file) |sf| {
|
||||
if (self.import_sources) |is| {
|
||||
|
||||
Reference in New Issue
Block a user