| author | |
| committer | |
| log | abf5ae6897bb23e49e4232ab8be7ed61ea9520b6 |
| tree | a0ff1d117e79a63827995c65d22a3fc4e46a37e1 |
| parent | b8f59e14cdbf90cf724ed9e721c1909293f41b3b |
8 files changed, 55 insertions(+), 20 deletions(-)
TODO+4| ... | @@ -25,3 +25,7 @@ comptime test for err | ... | @@ -25,3 +25,7 @@ comptime test for err |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | undefined in infer error | 27 | undefined in infer error |
| 28 | |||
| 29 | change readlink back to inferred error | ||
| 30 | |||
| 31 | syntax - ?a!b should be ?(a!b) but it's (?a)!b |
src/ir.cpp+29-2| ... | @@ -10123,6 +10123,13 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira, | ... | @@ -10123,6 +10123,13 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira, |
| 10123 | if (type_is_invalid(payload_type)) | 10123 | if (type_is_invalid(payload_type)) |
| 10124 | return ira->codegen->builtin_types.entry_invalid; | 10124 | return ira->codegen->builtin_types.entry_invalid; |
| 10125 | 10125 | ||
| 10126 | if (err_set_type->id != TypeTableEntryIdErrorSet) { | ||
| 10127 | ir_add_error(ira, instruction->err_set->other, | ||
| 10128 | buf_sprintf("expected error set type, found type '%s'", | ||
| 10129 | buf_ptr(&err_set_type->name))); | ||
| 10130 | return ira->codegen->builtin_types.entry_invalid; | ||
| 10131 | } | ||
| 10132 | |||
| 10126 | TypeTableEntry *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type); | 10133 | TypeTableEntry *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type); |
| 10127 | 10134 | ||
| 10128 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 10135 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| ... | @@ -10412,9 +10419,17 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -10412,9 +10419,17 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 10412 | } | 10419 | } |
| 10413 | 10420 | ||
| 10414 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; | 10421 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 10415 | TypeTableEntry *return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node); | 10422 | TypeTableEntry *specified_return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node); |
| 10416 | if (type_is_invalid(return_type)) | 10423 | if (type_is_invalid(specified_return_type)) |
| 10417 | return ira->codegen->builtin_types.entry_invalid; | 10424 | return ira->codegen->builtin_types.entry_invalid; |
| 10425 | TypeTableEntry *return_type; | ||
| 10426 | TypeTableEntry *inferred_err_set_type = nullptr; | ||
| 10427 | if (fn_proto_node->data.fn_proto.auto_err_set) { | ||
| 10428 | inferred_err_set_type = get_auto_err_set_type(ira->codegen, fn_entry); | ||
| 10429 | return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type); | ||
| 10430 | } else { | ||
| 10431 | return_type = specified_return_type; | ||
| 10432 | } | ||
| 10418 | 10433 | ||
| 10419 | IrInstruction *result; | 10434 | IrInstruction *result; |
| 10420 | 10435 | ||
| ... | @@ -10428,6 +10443,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -10428,6 +10443,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 10428 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, | 10443 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, |
| 10429 | nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec); | 10444 | nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec); |
| 10430 | 10445 | ||
| 10446 | if (inferred_err_set_type != nullptr) { | ||
| 10447 | inferred_err_set_type->data.error_set.infer_fn = nullptr; | ||
| 10448 | if (result->value.type->id == TypeTableEntryIdErrorUnion) { | ||
| 10449 | TypeTableEntry *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type; | ||
| 10450 | inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count; | ||
| 10451 | inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors; | ||
| 10452 | } else if (result->value.type->id == TypeTableEntryIdErrorSet) { | ||
| 10453 | inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count; | ||
| 10454 | inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors; | ||
| 10455 | } | ||
| 10456 | } | ||
| 10457 | |||
| 10431 | ira->codegen->memoized_fn_eval_table.put(exec_scope, result); | 10458 | ira->codegen->memoized_fn_eval_table.put(exec_scope, result); |
| 10432 | 10459 | ||
| 10433 | if (type_is_invalid(result->value.type)) | 10460 | if (type_is_invalid(result->value.type)) |
src/parser.cpp+1-1| ... | @@ -2589,7 +2589,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, | ... | @@ -2589,7 +2589,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2589 | Token *colon_token = &pc->tokens->at(*token_index); | 2589 | Token *colon_token = &pc->tokens->at(*token_index); |
| 2590 | if (colon_token->id == TokenIdColon) { | 2590 | if (colon_token->id == TokenIdColon) { |
| 2591 | *token_index += 1; | 2591 | *token_index += 1; |
| 2592 | field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true); | 2592 | field_node->data.struct_field.type = ast_parse_type_expr(pc, token_index, true); |
| 2593 | } | 2593 | } |
| 2594 | Token *eq_token = &pc->tokens->at(*token_index); | 2594 | Token *eq_token = &pc->tokens->at(*token_index); |
| 2595 | if (eq_token->id == TokenIdEq) { | 2595 | if (eq_token->id == TokenIdEq) { |
std/base64.zig+3-3| ... | @@ -181,7 +181,7 @@ pub const Base64DecoderWithIgnore = struct { | ... | @@ -181,7 +181,7 @@ pub const Base64DecoderWithIgnore = struct { |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | /// If no characters end up being ignored or padding, this will be the exact decoded size. | 183 | /// If no characters end up being ignored or padding, this will be the exact decoded size. |
| 184 | pub fn calcSizeUpperBound(encoded_len: usize) !usize { | 184 | pub fn calcSizeUpperBound(encoded_len: usize) usize { |
| 185 | return @divTrunc(encoded_len, 4) * 3; | 185 | return @divTrunc(encoded_len, 4) * 3; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| ... | @@ -430,7 +430,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void | ... | @@ -430,7 +430,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void |
| 430 | const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init( | 430 | const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init( |
| 431 | standard_alphabet_chars, standard_pad_char, ""); | 431 | standard_alphabet_chars, standard_pad_char, ""); |
| 432 | var buffer: [0x100]u8 = undefined; | 432 | var buffer: [0x100]u8 = undefined; |
| 433 | var decoded = buffer[0..try Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)]; | 433 | var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)]; |
| 434 | var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded); | 434 | var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded); |
| 435 | assert(written <= decoded.len); | 435 | assert(written <= decoded.len); |
| 436 | assert(mem.eql(u8, decoded[0..written], expected_decoded)); | 436 | assert(mem.eql(u8, decoded[0..written], expected_decoded)); |
| ... | @@ -449,7 +449,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi | ... | @@ -449,7 +449,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi |
| 449 | const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( | 449 | const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( |
| 450 | standard_alphabet_chars, standard_pad_char, " "); | 450 | standard_alphabet_chars, standard_pad_char, " "); |
| 451 | var buffer: [0x100]u8 = undefined; | 451 | var buffer: [0x100]u8 = undefined; |
| 452 | var decoded = buffer[0..try Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)]; | 452 | var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)]; |
| 453 | var written = try standard_decoder_ignore_space.decode(decoded, encoded); | 453 | var written = try standard_decoder_ignore_space.decode(decoded, encoded); |
| 454 | assert(mem.eql(u8, decoded[0..written], expected_decoded)); | 454 | assert(mem.eql(u8, decoded[0..written], expected_decoded)); |
| 455 | } | 455 | } |
std/build.zig+5-5| ... | @@ -554,7 +554,7 @@ pub const Builder = struct { | ... | @@ -554,7 +554,7 @@ pub const Builder = struct { |
| 554 | } | 554 | } |
| 555 | 555 | ||
| 556 | fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, | 556 | fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, |
| 557 | argv: []const []const u8) %void | 557 | argv: []const []const u8) !void |
| 558 | { | 558 | { |
| 559 | if (self.verbose) { | 559 | if (self.verbose) { |
| 560 | printCmd(cwd, argv); | 560 | printCmd(cwd, argv); |
| ... | @@ -1942,12 +1942,12 @@ pub const RemoveDirStep = struct { | ... | @@ -1942,12 +1942,12 @@ pub const RemoveDirStep = struct { |
| 1942 | 1942 | ||
| 1943 | pub const Step = struct { | 1943 | pub const Step = struct { |
| 1944 | name: []const u8, | 1944 | name: []const u8, |
| 1945 | makeFn: fn(self: &Step) %void, | 1945 | makeFn: fn(self: &Step) error!void, |
| 1946 | dependencies: ArrayList(&Step), | 1946 | dependencies: ArrayList(&Step), |
| 1947 | loop_flag: bool, | 1947 | loop_flag: bool, |
| 1948 | done_flag: bool, | 1948 | done_flag: bool, |
| 1949 | 1949 | ||
| 1950 | pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)%void) Step { | 1950 | pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)error!void) Step { |
| 1951 | return Step { | 1951 | return Step { |
| 1952 | .name = name, | 1952 | .name = name, |
| 1953 | .makeFn = makeFn, | 1953 | .makeFn = makeFn, |
| ... | @@ -1972,11 +1972,11 @@ pub const Step = struct { | ... | @@ -1972,11 +1972,11 @@ pub const Step = struct { |
| 1972 | self.dependencies.append(other) catch unreachable; | 1972 | self.dependencies.append(other) catch unreachable; |
| 1973 | } | 1973 | } |
| 1974 | 1974 | ||
| 1975 | fn makeNoOp(self: &Step) %void {} | 1975 | fn makeNoOp(self: &Step) (error{}!void) {} |
| 1976 | }; | 1976 | }; |
| 1977 | 1977 | ||
| 1978 | fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, | 1978 | fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, |
| 1979 | filename_name_only: []const u8) %void | 1979 | filename_name_only: []const u8) !void |
| 1980 | { | 1980 | { |
| 1981 | const out_dir = os.path.dirname(output_path); | 1981 | const out_dir = os.path.dirname(output_path); |
| 1982 | const out_basename = os.path.basename(output_path); | 1982 | const out_basename = os.path.basename(output_path); |
std/fmt/index.zig+3-3| ... | @@ -198,7 +198,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@ | ... | @@ -198,7 +198,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@ |
| 198 | return formatInt(value, 10, false, 0, context, Errors, output); | 198 | return formatInt(value, 10, false, 0, context, Errors, output); |
| 199 | }, | 199 | }, |
| 200 | builtin.TypeId.Float => { | 200 | builtin.TypeId.Float => { |
| 201 | return formatFloat(value, context, output); | 201 | return formatFloat(value, context, Errors, output); |
| 202 | }, | 202 | }, |
| 203 | builtin.TypeId.Void => { | 203 | builtin.TypeId.Void => { |
| 204 | return output(context, "void"); | 204 | return output(context, "void"); |
| ... | @@ -417,7 +417,7 @@ const FormatIntBuf = struct { | ... | @@ -417,7 +417,7 @@ const FormatIntBuf = struct { |
| 417 | out_buf: []u8, | 417 | out_buf: []u8, |
| 418 | index: usize, | 418 | index: usize, |
| 419 | }; | 419 | }; |
| 420 | fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) !void { | 420 | fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) (error{}!void) { |
| 421 | mem.copy(u8, context.out_buf[context.index..], bytes); | 421 | mem.copy(u8, context.out_buf[context.index..], bytes); |
| 422 | context.index += bytes.len; | 422 | context.index += bytes.len; |
| 423 | } | 423 | } |
| ... | @@ -499,7 +499,7 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void { | ... | @@ -499,7 +499,7 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void { |
| 499 | 499 | ||
| 500 | pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 { | 500 | pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 { |
| 501 | var context = BufPrintContext { .remaining = buf, }; | 501 | var context = BufPrintContext { .remaining = buf, }; |
| 502 | try format(&context, bufPrintWrite, fmt, args); | 502 | try format(&context, error{BufferTooSmall}, bufPrintWrite, fmt, args); |
| 503 | return buf[0..buf.len - context.remaining.len]; | 503 | return buf[0..buf.len - context.remaining.len]; |
| 504 | } | 504 | } |
| 505 | 505 |
std/os/child_process.zig+8-4| ... | @@ -28,7 +28,7 @@ pub const ChildProcess = struct { | ... | @@ -28,7 +28,7 @@ pub const ChildProcess = struct { |
| 28 | pub stdout: ?io.File, | 28 | pub stdout: ?io.File, |
| 29 | pub stderr: ?io.File, | 29 | pub stderr: ?io.File, |
| 30 | 30 | ||
| 31 | pub term: ?%Term, | 31 | pub term: ?SpawnError!Term, |
| 32 | 32 | ||
| 33 | pub argv: []const []const u8, | 33 | pub argv: []const []const u8, |
| 34 | 34 | ||
| ... | @@ -54,6 +54,10 @@ pub const ChildProcess = struct { | ... | @@ -54,6 +54,10 @@ pub const ChildProcess = struct { |
| 54 | err_pipe: if (is_windows) void else [2]i32, | 54 | err_pipe: if (is_windows) void else [2]i32, |
| 55 | llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, | 55 | llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, |
| 56 | 56 | ||
| 57 | pub const SpawnError = error { | ||
| 58 | |||
| 59 | }; | ||
| 60 | |||
| 57 | pub const Term = union(enum) { | 61 | pub const Term = union(enum) { |
| 58 | Exited: i32, | 62 | Exited: i32, |
| 59 | Signal: i32, | 63 | Signal: i32, |
| ... | @@ -185,7 +189,7 @@ pub const ChildProcess = struct { | ... | @@ -185,7 +189,7 @@ pub const ChildProcess = struct { |
| 185 | /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. | 189 | /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. |
| 186 | /// If it succeeds, the caller owns result.stdout and result.stderr memory. | 190 | /// If it succeeds, the caller owns result.stdout and result.stderr memory. |
| 187 | pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, | 191 | pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, |
| 188 | env_map: ?&const BufMap, max_output_size: usize) %ExecResult | 192 | env_map: ?&const BufMap, max_output_size: usize) !ExecResult |
| 189 | { | 193 | { |
| 190 | const child = try ChildProcess.init(argv, allocator); | 194 | const child = try ChildProcess.init(argv, allocator); |
| 191 | defer child.deinit(); | 195 | defer child.deinit(); |
| ... | @@ -246,7 +250,7 @@ pub const ChildProcess = struct { | ... | @@ -246,7 +250,7 @@ pub const ChildProcess = struct { |
| 246 | fn waitUnwrappedWindows(self: &ChildProcess) !void { | 250 | fn waitUnwrappedWindows(self: &ChildProcess) !void { |
| 247 | const result = os.windowsWaitSingle(self.handle, windows.INFINITE); | 251 | const result = os.windowsWaitSingle(self.handle, windows.INFINITE); |
| 248 | 252 | ||
| 249 | self.term = (%Term)(x: { | 253 | self.term = (SpawnError!Term)(x: { |
| 250 | var exit_code: windows.DWORD = undefined; | 254 | var exit_code: windows.DWORD = undefined; |
| 251 | if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { | 255 | if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { |
| 252 | break :x Term { .Unknown = 0 }; | 256 | break :x Term { .Unknown = 0 }; |
| ... | @@ -631,7 +635,7 @@ pub const ChildProcess = struct { | ... | @@ -631,7 +635,7 @@ pub const ChildProcess = struct { |
| 631 | }; | 635 | }; |
| 632 | 636 | ||
| 633 | fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, | 637 | fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, |
| 634 | lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) %void | 638 | lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void |
| 635 | { | 639 | { |
| 636 | if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, | 640 | if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, |
| 637 | @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) | 641 | @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) |
std/os/index.zig+2-2| ... | @@ -1072,7 +1072,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) !void { | ... | @@ -1072,7 +1072,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) !void { |
| 1072 | } | 1072 | } |
| 1073 | 1073 | ||
| 1074 | /// Read value of a symbolic link. | 1074 | /// Read value of a symbolic link. |
| 1075 | pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 { | 1075 | pub fn readLink(allocator: &Allocator, pathname: []const u8) error![]u8 { |
| 1076 | const path_buf = try allocator.alloc(u8, pathname.len + 1); | 1076 | const path_buf = try allocator.alloc(u8, pathname.len + 1); |
| 1077 | defer allocator.free(path_buf); | 1077 | defer allocator.free(path_buf); |
| 1078 | 1078 | ||
| ... | @@ -1267,7 +1267,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1267,7 +1267,7 @@ pub const ArgIteratorWindows = struct { |
| 1267 | } | 1267 | } |
| 1268 | 1268 | ||
| 1269 | /// You must free the returned memory when done. | 1269 | /// You must free the returned memory when done. |
| 1270 | pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?internalNext.errors![]u8 { | 1270 | pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?(@typeOf(internalNext).ReturnType.ErrorSet![]u8) { |
| 1271 | // march forward over whitespace | 1271 | // march forward over whitespace |
| 1272 | while (true) : (self.index += 1) { | 1272 | while (true) : (self.index += 1) { |
| 1273 | const byte = self.cmd_line[self.index]; | 1273 | const byte = self.cmd_line[self.index]; |