diff --git a/src/ir.cpp b/src/ir.cpp index 61c26cb5ae..2bb40c7e15 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15663,13 +15663,19 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira field_prev_uses[start_index] = start_value->source_node; } if (!instruction->have_else_prong) { - for (uint32_t i = 0; i < switch_type->data.error_set.err_count; i += 1) { - ErrorTableEntry *err_entry = switch_type->data.error_set.errors[i]; + if (type_is_global_error_set(switch_type)) { + ir_add_error(ira, &instruction->base, + buf_sprintf("else prong required when switching on type 'error'")); + return ira->codegen->builtin_types.entry_invalid; + } else { + for (uint32_t i = 0; i < switch_type->data.error_set.err_count; i += 1) { + ErrorTableEntry *err_entry = switch_type->data.error_set.errors[i]; - AstNode *prev_node = field_prev_uses[err_entry->value]; - if (prev_node == nullptr) { - ir_add_error(ira, &instruction->base, - buf_sprintf("error.%s not handled in switch", buf_ptr(&err_entry->name))); + AstNode *prev_node = field_prev_uses[err_entry->value]; + if (prev_node == nullptr) { + ir_add_error(ira, &instruction->base, + buf_sprintf("error.%s not handled in switch", buf_ptr(&err_entry->name))); + } } } } diff --git a/std/io.zig b/std/io.zig index dbaf39ea16..504dcdef80 100644 --- a/std/io.zig +++ b/std/io.zig @@ -499,7 +499,7 @@ pub fn OutStream(comptime Error: type) type { writeFn: fn(self: &Self, bytes: []const u8) Error!void, pub fn print(self: &Self, comptime format: []const u8, args: ...) !void { - return std.fmt.format(self, error, self.writeFn, format, args); + return std.fmt.format(self, Error, self.writeFn, format, args); } pub fn write(self: &Self, bytes: []const u8) !void { diff --git a/std/zig/parser.zig b/std/zig/parser.zig index 4fcdddf63d..9a2044c232 100644 --- a/std/zig/parser.zig +++ b/std/zig/parser.zig @@ -133,7 +133,6 @@ pub const Parser = struct { Token.Id.Eof => return Tree {.root_node = root_node}, else => { self.putBackToken(token); - // TODO shouldn't need this cast stack.append(State { .TopLevelExtern = null }) catch unreachable; continue; }, @@ -707,7 +706,7 @@ pub const Parser = struct { return node; } - fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) error { + fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) { const loc = self.tokenizer.getTokenLocation(token); warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args); warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]); @@ -1082,16 +1081,18 @@ fn testCanonical(source: []const u8) !void { var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index); if (testParse(source, &failing_allocator.allocator)) |_| { return error.NondeterministicMemoryUsage; - } else |err| { - assert(err == error.OutOfMemory); - // TODO make this pass - //if (failing_allocator.allocated_bytes != failing_allocator.freed_bytes) { - // warn("\nfail_index: {}/{}\nallocated bytes: {}\nfreed bytes: {}\nallocations: {}\ndeallocations: {}\n", - // fail_index, needed_alloc_count, - // failing_allocator.allocated_bytes, failing_allocator.freed_bytes, - // failing_allocator.index, failing_allocator.deallocations); - // return error.MemoryLeakDetected; - //} + } else |err| switch (err) { + error.OutOfMemory => { + // TODO make this pass + //if (failing_allocator.allocated_bytes != failing_allocator.freed_bytes) { + // warn("\nfail_index: {}/{}\nallocated bytes: {}\nfreed bytes: {}\nallocations: {}\ndeallocations: {}\n", + // fail_index, needed_alloc_count, + // failing_allocator.allocated_bytes, failing_allocator.freed_bytes, + // failing_allocator.index, failing_allocator.deallocations); + // return error.MemoryLeakDetected; + //} + }, + error.ParseError => @panic("test failed"), } } } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 3120e3a94a..f60705aa31 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,18 @@ const tests = @import("tests.zig"); pub fn addCases(cases: &tests.CompileErrorContext) void { + cases.add("no else prong on switch on global error set", + \\export fn entry() void { + \\ foo(error.A); + \\} + \\fn foo(a: error) void { + \\ switch (a) { + \\ error.A => {}, + \\ } + \\} + , + ".tmp_source.zig:5:5: error: else prong required when switching on type 'error'"); + cases.add("inferred error set with no returned error", \\export fn entry() void { \\ foo() catch unreachable;