diff --git a/TODO b/TODO index c6fcfa939a..69521fe204 100644 --- a/TODO +++ b/TODO @@ -25,3 +25,7 @@ comptime test for err undefined in infer error + +change readlink back to inferred error + +syntax - ?a!b should be ?(a!b) but it's (?a)!b diff --git a/src/ir.cpp b/src/ir.cpp index 12dc76e972..721bd70f12 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10123,6 +10123,13 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira, if (type_is_invalid(payload_type)) return ira->codegen->builtin_types.entry_invalid; + if (err_set_type->id != TypeTableEntryIdErrorSet) { + ir_add_error(ira, instruction->err_set->other, + buf_sprintf("expected error set type, found type '%s'", + buf_ptr(&err_set_type->name))); + return ira->codegen->builtin_types.entry_invalid; + } + TypeTableEntry *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type); ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); @@ -10412,9 +10419,17 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal } AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; - TypeTableEntry *return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node); - if (type_is_invalid(return_type)) + TypeTableEntry *specified_return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node); + if (type_is_invalid(specified_return_type)) return ira->codegen->builtin_types.entry_invalid; + TypeTableEntry *return_type; + TypeTableEntry *inferred_err_set_type = nullptr; + if (fn_proto_node->data.fn_proto.auto_err_set) { + inferred_err_set_type = get_auto_err_set_type(ira->codegen, fn_entry); + return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type); + } else { + return_type = specified_return_type; + } IrInstruction *result; @@ -10428,6 +10443,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec); + if (inferred_err_set_type != nullptr) { + inferred_err_set_type->data.error_set.infer_fn = nullptr; + if (result->value.type->id == TypeTableEntryIdErrorUnion) { + TypeTableEntry *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type; + inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count; + inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors; + } else if (result->value.type->id == TypeTableEntryIdErrorSet) { + inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count; + inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors; + } + } + ira->codegen->memoized_fn_eval_table.put(exec_scope, result); if (type_is_invalid(result->value.type)) diff --git a/src/parser.cpp b/src/parser.cpp index 1a3b568a2e..b72de374ba 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2589,7 +2589,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, Token *colon_token = &pc->tokens->at(*token_index); if (colon_token->id == TokenIdColon) { *token_index += 1; - field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true); + field_node->data.struct_field.type = ast_parse_type_expr(pc, token_index, true); } Token *eq_token = &pc->tokens->at(*token_index); if (eq_token->id == TokenIdEq) { diff --git a/std/base64.zig b/std/base64.zig index f91c1e56d6..d9e1d2f908 100644 --- a/std/base64.zig +++ b/std/base64.zig @@ -181,7 +181,7 @@ pub const Base64DecoderWithIgnore = struct { } /// If no characters end up being ignored or padding, this will be the exact decoded size. - pub fn calcSizeUpperBound(encoded_len: usize) !usize { + pub fn calcSizeUpperBound(encoded_len: usize) usize { return @divTrunc(encoded_len, 4) * 3; } @@ -430,7 +430,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init( standard_alphabet_chars, standard_pad_char, ""); var buffer: [0x100]u8 = undefined; - var decoded = buffer[0..try Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)]; + var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)]; var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded); assert(written <= decoded.len); assert(mem.eql(u8, decoded[0..written], expected_decoded)); @@ -449,7 +449,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( standard_alphabet_chars, standard_pad_char, " "); var buffer: [0x100]u8 = undefined; - var decoded = buffer[0..try Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)]; + var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)]; var written = try standard_decoder_ignore_space.decode(decoded, encoded); assert(mem.eql(u8, decoded[0..written], expected_decoded)); } diff --git a/std/build.zig b/std/build.zig index 1a5c48e684..216699f355 100644 --- a/std/build.zig +++ b/std/build.zig @@ -554,7 +554,7 @@ pub const Builder = struct { } fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, - argv: []const []const u8) %void + argv: []const []const u8) !void { if (self.verbose) { printCmd(cwd, argv); @@ -1942,12 +1942,12 @@ pub const RemoveDirStep = struct { pub const Step = struct { name: []const u8, - makeFn: fn(self: &Step) %void, + makeFn: fn(self: &Step) error!void, dependencies: ArrayList(&Step), loop_flag: bool, done_flag: bool, - pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)%void) Step { + pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)error!void) Step { return Step { .name = name, .makeFn = makeFn, @@ -1972,11 +1972,11 @@ pub const Step = struct { self.dependencies.append(other) catch unreachable; } - fn makeNoOp(self: &Step) %void {} + fn makeNoOp(self: &Step) (error{}!void) {} }; fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, - filename_name_only: []const u8) %void + filename_name_only: []const u8) !void { const out_dir = os.path.dirname(output_path); const out_basename = os.path.basename(output_path); diff --git a/std/fmt/index.zig b/std/fmt/index.zig index 26583817e6..50f0013852 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -198,7 +198,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@ return formatInt(value, 10, false, 0, context, Errors, output); }, builtin.TypeId.Float => { - return formatFloat(value, context, output); + return formatFloat(value, context, Errors, output); }, builtin.TypeId.Void => { return output(context, "void"); @@ -417,7 +417,7 @@ const FormatIntBuf = struct { out_buf: []u8, index: usize, }; -fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) !void { +fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) (error{}!void) { mem.copy(u8, context.out_buf[context.index..], bytes); context.index += bytes.len; } @@ -499,7 +499,7 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void { pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 { var context = BufPrintContext { .remaining = buf, }; - try format(&context, bufPrintWrite, fmt, args); + try format(&context, error{BufferTooSmall}, bufPrintWrite, fmt, args); return buf[0..buf.len - context.remaining.len]; } diff --git a/std/os/child_process.zig b/std/os/child_process.zig index c86db9d69c..48f638e323 100644 --- a/std/os/child_process.zig +++ b/std/os/child_process.zig @@ -28,7 +28,7 @@ pub const ChildProcess = struct { pub stdout: ?io.File, pub stderr: ?io.File, - pub term: ?%Term, + pub term: ?SpawnError!Term, pub argv: []const []const u8, @@ -54,6 +54,10 @@ pub const ChildProcess = struct { err_pipe: if (is_windows) void else [2]i32, llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, + pub const SpawnError = error { + + }; + pub const Term = union(enum) { Exited: i32, Signal: i32, @@ -185,7 +189,7 @@ pub const ChildProcess = struct { /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. /// If it succeeds, the caller owns result.stdout and result.stderr memory. pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, - env_map: ?&const BufMap, max_output_size: usize) %ExecResult + env_map: ?&const BufMap, max_output_size: usize) !ExecResult { const child = try ChildProcess.init(argv, allocator); defer child.deinit(); @@ -246,7 +250,7 @@ pub const ChildProcess = struct { fn waitUnwrappedWindows(self: &ChildProcess) !void { const result = os.windowsWaitSingle(self.handle, windows.INFINITE); - self.term = (%Term)(x: { + self.term = (SpawnError!Term)(x: { var exit_code: windows.DWORD = undefined; if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { break :x Term { .Unknown = 0 }; @@ -631,7 +635,7 @@ pub const ChildProcess = struct { }; fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, - lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) %void + lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void { if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) diff --git a/std/os/index.zig b/std/os/index.zig index a303ee4be1..aad24cf996 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -1072,7 +1072,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) !void { } /// Read value of a symbolic link. -pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 { +pub fn readLink(allocator: &Allocator, pathname: []const u8) error![]u8 { const path_buf = try allocator.alloc(u8, pathname.len + 1); defer allocator.free(path_buf); @@ -1267,7 +1267,7 @@ pub const ArgIteratorWindows = struct { } /// You must free the returned memory when done. - pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?internalNext.errors![]u8 { + pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?(@typeOf(internalNext).ReturnType.ErrorSet![]u8) { // march forward over whitespace while (true) : (self.index += 1) { const byte = self.cmd_line[self.index];