From f99b8b006fe458ee717acc6c8de6170fc453acb7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 5 Feb 2018 18:09:13 -0500 Subject: [PATCH] error sets - fix most std lib compile errors --- src/ir.cpp | 20 +++++++++++++++++++- std/fmt/index.zig | 8 ++++---- std/io.zig | 39 ++++++++++++++++++++++++--------------- std/io_test.zig | 4 ++-- 4 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 0f9020c9d..c9c73c66f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -9361,6 +9361,24 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp ir_add_error_node(ira, source_node, buf_sprintf("operator not allowed for errors")); return ira->codegen->builtin_types.entry_invalid; } + // exception if one of the operators has the type of the empty error set, we allow the comparison + // (and make it comptime known) + // this is a function which is evaluated at comptime and returns an inferred error set will have an empty + // error set. + if (op1->value.type->data.error_set.err_count == 0 || op2->value.type->data.error_set.err_count == 0) { + bool are_equal = false; + bool answer; + if (op_id == IrBinOpCmpEq) { + answer = are_equal; + } else if (op_id == IrBinOpCmpNotEq) { + answer = !are_equal; + } else { + zig_unreachable(); + } + ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base); + out_val->data.x_bool = answer; + return ira->codegen->builtin_types.entry_bool; + } TypeTableEntry *intersect_type = get_error_set_intersection(ira, op1->value.type, op2->value.type, source_node); if (type_is_invalid(intersect_type)) { return ira->codegen->builtin_types.entry_invalid; @@ -15352,7 +15370,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, ErrorTableEntry *err = err_union_val->data.x_err_union.err; if (err != nullptr) { ir_add_error(ira, &instruction->base, - buf_sprintf("unable to unwrap error '%s'", buf_ptr(&err->name))); + buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name))); return ira->codegen->builtin_types.entry_invalid; } diff --git a/std/fmt/index.zig b/std/fmt/index.zig index 50f001385..407ffd901 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -439,9 +439,9 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { test "fmt.parseInt" { assert((parseInt(i32, "-10", 10) catch unreachable) == -10); assert((parseInt(i32, "+10", 10) catch unreachable) == 10); - assert(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidChar); - assert(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidChar); - assert(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidChar); + assert(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter); + assert(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter); + assert(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter); assert((parseInt(u8, "255", 10) catch unreachable) == 255); assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow); } @@ -538,7 +538,7 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: u test "parse u64 digit too big" { _ = parseUnsigned(u64, "123a", 10) catch |err| { - if (err == error.InvalidChar) return; + if (err == error.InvalidCharacter) return; unreachable; }; unreachable; diff --git a/std/io.zig b/std/io.zig index 50b70db64..842c30a0e 100644 --- a/std/io.zig +++ b/std/io.zig @@ -550,21 +550,24 @@ pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len return buf; } -pub const BufferedInStream = BufferedInStreamCustom(os.page_size); +pub fn BufferedInStream(comptime Error: type) type { + return BufferedInStreamCustom(os.page_size, Error); +} -pub fn BufferedInStreamCustom(comptime buffer_size: usize) type { +pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type { return struct { const Self = this; + const Stream = InStream(Error); - pub stream: InStream, + pub stream: Stream, - unbuffered_in_stream: &InStream, + unbuffered_in_stream: &Stream, buffer: [buffer_size]u8, start_index: usize, end_index: usize, - pub fn init(unbuffered_in_stream: &InStream) Self { + pub fn init(unbuffered_in_stream: &Stream) Self { return Self { .unbuffered_in_stream = unbuffered_in_stream, .buffer = undefined, @@ -576,13 +579,13 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) type { .start_index = buffer_size, .end_index = buffer_size, - .stream = InStream { + .stream = Stream { .readFn = readFn, }, }; } - fn readFn(in_stream: &InStream, dest: []u8) !usize { + fn readFn(in_stream: &Stream, dest: []u8) !usize { const self = @fieldParentPtr(Self, "stream", in_stream); var dest_index: usize = 0; @@ -621,25 +624,28 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) type { }; } -pub const BufferedOutStream = BufferedOutStreamCustom(os.page_size); +pub fn BufferedOutStream(comptime Error: type) type { + return BufferedOutStreamCustom(os.page_size, Error); +} -pub fn BufferedOutStreamCustom(comptime buffer_size: usize) type { +pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime Error: type) type { return struct { const Self = this; + const Stream = OutStream(Error); - pub stream: OutStream, + pub stream: Stream, - unbuffered_out_stream: &OutStream, + unbuffered_out_stream: &Stream, buffer: [buffer_size]u8, index: usize, - pub fn init(unbuffered_out_stream: &OutStream) Self { + pub fn init(unbuffered_out_stream: &Stream) Self { return Self { .unbuffered_out_stream = unbuffered_out_stream, .buffer = undefined, .index = 0, - .stream = OutStream { + .stream = Stream { .writeFn = writeFn, }, }; @@ -653,7 +659,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) type { self.index = 0; } - fn writeFn(out_stream: &OutStream, bytes: []const u8) !void { + fn writeFn(out_stream: &Stream, bytes: []const u8) !void { const self = @fieldParentPtr(Self, "stream", out_stream); if (bytes.len >= self.buffer.len) { @@ -680,7 +686,10 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) type { /// Implementation of OutStream trait for Buffer pub const BufferOutStream = struct { buffer: &Buffer, - stream: OutStream, + stream: Stream, + + pub const Error = error{OutOfMemory}; + pub const Stream = OutStream(Error); pub fn init(buffer: &Buffer) BufferOutStream { return BufferOutStream { diff --git a/std/io_test.zig b/std/io_test.zig index 1767a546e..ea4b816b0 100644 --- a/std/io_test.zig +++ b/std/io_test.zig @@ -17,7 +17,7 @@ test "write a file, read it, then delete it" { defer file.close(); var file_out_stream = io.FileOutStream.init(&file); - var buf_stream = io.BufferedOutStream.init(&file_out_stream.stream); + var buf_stream = io.BufferedOutStream(io.FileOutStream.Error).init(&file_out_stream.stream); const st = &buf_stream.stream; try st.print("begin"); try st.write(data[0..]); @@ -33,7 +33,7 @@ test "write a file, read it, then delete it" { assert(file_size == expected_file_size); var file_in_stream = io.FileInStream.init(&file); - var buf_stream = io.BufferedInStream.init(&file_in_stream.stream); + var buf_stream = io.BufferedInStream(io.FileInStream.Error).init(&file_in_stream.stream); const st = &buf_stream.stream; const contents = try st.readAllAlloc(allocator, 2 * 1024); defer allocator.free(contents);