authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-10 23:27:17+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-10 23:27:17+02:00
logb316c25cc6f5b1703d7912da16c5c987f4406451
treeffa2e42d540261808d3a854efa1fc6061e6dc925
parent1f8ae10a388bc2836c954c54fa487233fe045dd6
parent3ccd4907fbcd04ecddffb618a4b14581fd080279
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13075 from Vexu/stage2-fixes

Stage2 misc fixes

19 files changed, 424 insertions(+), 77 deletions(-)

src/AstGen.zig+3-1
...@@ -2506,10 +2506,10 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2506,10 +2506,10 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2506 .dbg_block_end,2506 .dbg_block_end,
2507 .ensure_result_used,2507 .ensure_result_used,
2508 .ensure_result_non_error,2508 .ensure_result_non_error,
2509 .ensure_err_union_payload_void,
2509 .@"export",2510 .@"export",
2510 .export_value,2511 .export_value,
2511 .set_eval_branch_quota,2512 .set_eval_branch_quota,
2512 .ensure_err_payload_void,
2513 .atomic_store,2513 .atomic_store,
2514 .store,2514 .store,
2515 .store_node,2515 .store_node,
...@@ -5499,6 +5499,7 @@ fn ifExpr(...@@ -5499,6 +5499,7 @@ fn ifExpr(
5499 try then_scope.addDbgVar(.dbg_var_val, ident_name, payload_inst);5499 try then_scope.addDbgVar(.dbg_var_val, ident_name, payload_inst);
5500 break :s &payload_val_scope.base;5500 break :s &payload_val_scope.base;
5501 } else {5501 } else {
5502 _ = try then_scope.addUnNode(.ensure_err_union_payload_void, cond.inst, node);
5502 break :s &then_scope.base;5503 break :s &then_scope.base;
5503 }5504 }
5504 } else if (if_full.payload_token) |payload_token| {5505 } else if (if_full.payload_token) |payload_token| {
...@@ -5836,6 +5837,7 @@ fn whileExpr(...@@ -5836,6 +5837,7 @@ fn whileExpr(
5836 dbg_var_inst = indexToRef(payload_inst);5837 dbg_var_inst = indexToRef(payload_inst);
5837 break :s &payload_val_scope.base;5838 break :s &payload_val_scope.base;
5838 } else {5839 } else {
5840 _ = try then_scope.addUnNode(.ensure_err_union_payload_void, cond.inst, node);
5839 break :s &then_scope.base;5841 break :s &then_scope.base;
5840 }5842 }
5841 } else if (while_full.payload_token) |payload_token| {5843 } else if (while_full.payload_token) |payload_token| {
src/Sema.zig+182-67
...@@ -1034,8 +1034,8 @@ fn analyzeBodyInner(...@@ -1034,8 +1034,8 @@ fn analyzeBodyInner(
1034 i += 1;1034 i += 1;
1035 continue;1035 continue;
1036 },1036 },
1037 .ensure_err_payload_void => {1037 .ensure_err_union_payload_void => {
1038 try sema.zirEnsureErrPayloadVoid(block, inst);1038 try sema.zirEnsureErrUnionPayloadVoid(block, inst);
1039 i += 1;1039 i += 1;
1040 continue;1040 continue;
1041 },1041 },
...@@ -1302,17 +1302,28 @@ fn analyzeBodyInner(...@@ -1302,17 +1302,28 @@ fn analyzeBodyInner(
1302 // current list of parameters and restore it later.1302 // current list of parameters and restore it later.
1303 // Note: this probably needs to be resolved in a more general manner.1303 // Note: this probably needs to be resolved in a more general manner.
1304 const prev_params = block.params;1304 const prev_params = block.params;
1305 const prev_inline_block = block.inline_block;1305 const need_sub_block = tags[inline_body[inline_body.len - 1]] == .repeat_inline;
1306 if (tags[inline_body[inline_body.len - 1]] == .repeat_inline) {1306 var sub_block = block;
1307 block.inline_block = inline_body[0];1307 var block_space: Block = undefined;
1308 // NOTE: this has to be done like this because branching in
1309 // defers here breaks stage1.
1310 block_space.instructions = .{};
1311 if (need_sub_block) {
1312 block_space = block.makeSubBlock();
1313 block_space.inline_block = inline_body[0];
1314 sub_block = &block_space;
1308 }1315 }
1309 block.params = .{};1316 block.params = .{};
1310 defer {1317 defer {
1311 block.params.deinit(gpa);1318 block.params.deinit(gpa);
1312 block.params = prev_params;1319 block.params = prev_params;
1313 block.inline_block = prev_inline_block;1320 block_space.instructions.deinit(gpa);
1314 }1321 }
1315 const opt_break_data = try sema.analyzeBodyBreak(block, inline_body);1322 const opt_break_data = try sema.analyzeBodyBreak(sub_block, inline_body);
1323 if (need_sub_block) {
1324 try block.instructions.appendSlice(gpa, block_space.instructions.items);
1325 }
1326
1316 // A runtime conditional branch that needs a post-hoc block to be1327 // A runtime conditional branch that needs a post-hoc block to be
1317 // emitted communicates this by mapping the block index into the inst map.1328 // emitted communicates this by mapping the block index into the inst map.
1318 if (map.get(inst)) |new_block_ref| ph: {1329 if (map.get(inst)) |new_block_ref| ph: {
...@@ -2469,7 +2480,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2469,7 +2480,7 @@ fn createAnonymousDeclTypeNamed(
2469 const arg = sema.inst_map.get(zir_inst).?;2480 const arg = sema.inst_map.get(zir_inst).?;
2470 // The comptime call code in analyzeCall already did this, so we're2481 // The comptime call code in analyzeCall already did this, so we're
2471 // just repeating it here and it's guaranteed to work.2482 // just repeating it here and it's guaranteed to work.
2472 const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg, undefined) catch unreachable;2483 const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg, "") catch unreachable;
24732484
2474 if (arg_i != 0) try buf.appendSlice(",");2485 if (arg_i != 0) try buf.appendSlice(",");
2475 try buf.writer().print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)});2486 try buf.writer().print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)});
...@@ -3089,6 +3100,33 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3089,6 +3100,33 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3089 }3100 }
3090}3101}
30913102
3103fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
3104 const tracy = trace(@src());
3105 defer tracy.end();
3106
3107 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3108 const src = inst_data.src();
3109 const operand = try sema.resolveInst(inst_data.operand);
3110 const operand_ty = sema.typeOf(operand);
3111 const err_union_ty = if (operand_ty.zigTypeTag() == .Pointer)
3112 operand_ty.childType()
3113 else
3114 operand_ty;
3115 // TODO this should be validated in a more generic instruction that is
3116 // emitted for all ifs and whiles with an error union condition.
3117 if (err_union_ty.zigTypeTag() != .ErrorUnion) return;
3118 const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag();
3119 if (payload_ty != .Void and payload_ty != .NoReturn) {
3120 const msg = msg: {
3121 const msg = try sema.errMsg(block, src, "error union payload is ignored", .{});
3122 errdefer msg.destroy(sema.gpa);
3123 try sema.errNote(block, src, msg, "payload value can be explicitly ignored with '|_|'", .{});
3124 break :msg msg;
3125 };
3126 return sema.failWithOwnedErrorMsg(msg);
3127 }
3128}
3129
3092fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {3130fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
3093 const tracy = trace(@src());3131 const tracy = trace(@src());
3094 defer tracy.end();3132 defer tracy.end();
...@@ -5631,7 +5669,7 @@ fn zirCall(...@@ -5631,7 +5669,7 @@ fn zirCall(
5631 var bound_arg_src: ?LazySrcLoc = null;5669 var bound_arg_src: ?LazySrcLoc = null;
5632 if (func_type.tag() == .bound_fn) {5670 if (func_type.tag() == .bound_fn) {
5633 bound_arg_src = func_src;5671 bound_arg_src = func_src;
5634 const bound_func = try sema.resolveValue(block, .unneeded, func, undefined);5672 const bound_func = try sema.resolveValue(block, .unneeded, func, "");
5635 const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;5673 const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
5636 func = bound_data.func_inst;5674 func = bound_data.func_inst;
5637 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len + 1);5675 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len + 1);
...@@ -6010,6 +6048,7 @@ fn analyzeCall(...@@ -6010,6 +6048,7 @@ fn analyzeCall(
6010 const parent_inst_map = sema.inst_map;6048 const parent_inst_map = sema.inst_map;
6011 sema.inst_map = .{};6049 sema.inst_map = .{};
6012 defer {6050 defer {
6051 sema.src = call_src;
6013 sema.inst_map.deinit(gpa);6052 sema.inst_map.deinit(gpa);
6014 sema.inst_map = parent_inst_map;6053 sema.inst_map = parent_inst_map;
6015 }6054 }
...@@ -6213,7 +6252,7 @@ fn analyzeCall(...@@ -6213,7 +6252,7 @@ fn analyzeCall(
6213 }6252 }
62146253
6215 if (should_memoize and is_comptime_call) {6254 if (should_memoize and is_comptime_call) {
6216 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, undefined);6255 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");
62176256
6218 // TODO: check whether any external comptime memory was mutated by the6257 // TODO: check whether any external comptime memory was mutated by the
6219 // comptime function call. If so, then do not memoize the call here.6258 // comptime function call. If so, then do not memoize the call here.
...@@ -6675,6 +6714,8 @@ fn instantiateGenericCall(...@@ -6675,6 +6714,8 @@ fn instantiateGenericCall(
6675 .comptime_args_fn_inst = module_fn.zir_body_inst,6714 .comptime_args_fn_inst = module_fn.zir_body_inst,
6676 .preallocated_new_func = new_module_func,6715 .preallocated_new_func = new_module_func,
6677 .is_generic_instantiation = true,6716 .is_generic_instantiation = true,
6717 .branch_quota = sema.branch_quota,
6718 .branch_count = sema.branch_count,
6678 };6719 };
6679 defer child_sema.deinit();6720 defer child_sema.deinit();
66806721
...@@ -6724,12 +6765,12 @@ fn instantiateGenericCall(...@@ -6724,12 +6765,12 @@ fn instantiateGenericCall(
6724 const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val);6765 const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val);
6725 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);6766 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
6726 } else {6767 } else {
6727 return sema.failWithNeededComptime(block, .unneeded, undefined);6768 return sema.failWithNeededComptime(block, .unneeded, "");
6728 }6769 }
6729 } else if (is_anytype) {6770 } else if (is_anytype) {
6730 const arg_ty = sema.typeOf(arg);6771 const arg_ty = sema.typeOf(arg);
6731 if (try sema.typeRequiresComptime(arg_ty)) {6772 if (try sema.typeRequiresComptime(arg_ty)) {
6732 const arg_val = try sema.resolveConstValue(block, .unneeded, arg, undefined);6773 const arg_val = try sema.resolveConstValue(block, .unneeded, arg, "");
6733 const child_arg = try child_sema.addConstant(arg_ty, arg_val);6774 const child_arg = try child_sema.addConstant(arg_ty, arg_val);
6734 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);6775 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
6735 } else {6776 } else {
...@@ -6751,7 +6792,7 @@ fn instantiateGenericCall(...@@ -6751,7 +6792,7 @@ fn instantiateGenericCall(
6751 }6792 }
6752 return err;6793 return err;
6753 };6794 };
6754 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;6795 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, "") catch unreachable;
6755 const new_func = new_func_val.castTag(.function).?.data;6796 const new_func = new_func_val.castTag(.function).?.data;
6756 errdefer new_func.deinit(gpa);6797 errdefer new_func.deinit(gpa);
6757 assert(new_func == new_module_func);6798 assert(new_func == new_module_func);
...@@ -7674,24 +7715,6 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -7674,24 +7715,6 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
7674 return block.addTyOp(.unwrap_errunion_err_ptr, result_ty, operand);7715 return block.addTyOp(.unwrap_errunion_err_ptr, result_ty, operand);
7675}7716}
76767717
7677fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
7678 const tracy = trace(@src());
7679 defer tracy.end();
7680
7681 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
7682 const src = inst_data.src();
7683 const operand = try sema.resolveInst(inst_data.operand);
7684 const operand_ty = sema.typeOf(operand);
7685 if (operand_ty.zigTypeTag() != .ErrorUnion) {
7686 return sema.fail(block, src, "expected error union type, found '{}'", .{
7687 operand_ty.fmt(sema.mod),
7688 });
7689 }
7690 if (operand_ty.errorUnionPayload().zigTypeTag() != .Void) {
7691 return sema.fail(block, src, "expression value is ignored", .{});
7692 }
7693}
7694
7695fn zirFunc(7718fn zirFunc(
7696 sema: *Sema,7719 sema: *Sema,
7697 block: *Block,7720 block: *Block,
...@@ -9119,7 +9142,7 @@ fn zirSwitchCapture(...@@ -9119,7 +9142,7 @@ fn zirSwitchCapture(
9119 const union_obj = operand_ty.cast(Type.Payload.Union).?.data;9142 const union_obj = operand_ty.cast(Type.Payload.Union).?.data;
9120 const first_item = try sema.resolveInst(items[0]);9143 const first_item = try sema.resolveInst(items[0]);
9121 // Previous switch validation ensured this will succeed9144 // Previous switch validation ensured this will succeed
9122 const first_item_val = sema.resolveConstValue(block, .unneeded, first_item, undefined) catch unreachable;9145 const first_item_val = sema.resolveConstValue(block, .unneeded, first_item, "") catch unreachable;
91239146
9124 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, sema.mod).?);9147 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, sema.mod).?);
9125 const first_field = union_obj.fields.values()[first_field_index];9148 const first_field = union_obj.fields.values()[first_field_index];
...@@ -9127,7 +9150,7 @@ fn zirSwitchCapture(...@@ -9127,7 +9150,7 @@ fn zirSwitchCapture(
9127 for (items[1..]) |item, i| {9150 for (items[1..]) |item, i| {
9128 const item_ref = try sema.resolveInst(item);9151 const item_ref = try sema.resolveInst(item);
9129 // Previous switch validation ensured this will succeed9152 // Previous switch validation ensured this will succeed
9130 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, undefined) catch unreachable;9153 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
91319154
9132 const field_index = operand_ty.unionTagFieldIndex(item_val, sema.mod).?;9155 const field_index = operand_ty.unionTagFieldIndex(item_val, sema.mod).?;
9133 const field = union_obj.fields.values()[field_index];9156 const field = union_obj.fields.values()[field_index];
...@@ -9188,7 +9211,7 @@ fn zirSwitchCapture(...@@ -9188,7 +9211,7 @@ fn zirSwitchCapture(
9188 for (items) |item| {9211 for (items) |item| {
9189 const item_ref = try sema.resolveInst(item);9212 const item_ref = try sema.resolveInst(item);
9190 // Previous switch validation ensured this will succeed9213 // Previous switch validation ensured this will succeed
9191 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, undefined) catch unreachable;9214 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
9192 names.putAssumeCapacityNoClobber(9215 names.putAssumeCapacityNoClobber(
9193 item_val.getError().?,9216 item_val.getError().?,
9194 {},9217 {},
...@@ -9202,7 +9225,7 @@ fn zirSwitchCapture(...@@ -9202,7 +9225,7 @@ fn zirSwitchCapture(
9202 } else {9225 } else {
9203 const item_ref = try sema.resolveInst(items[0]);9226 const item_ref = try sema.resolveInst(items[0]);
9204 // Previous switch validation ensured this will succeed9227 // Previous switch validation ensured this will succeed
9205 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, undefined) catch unreachable;9228 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
92069229
9207 const item_ty = try Type.Tag.error_set_single.create(sema.arena, item_val.getError().?);9230 const item_ty = try Type.Tag.error_set_single.create(sema.arena, item_val.getError().?);
9208 return sema.bitCast(block, item_ty, operand, operand_src);9231 return sema.bitCast(block, item_ty, operand, operand_src);
...@@ -9941,14 +9964,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9941,14 +9964,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9941 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);9964 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
9942 extra_index += 1;9965 extra_index += 1;
9943 const body_len = @truncate(u31, sema.code.extra[extra_index]);9966 const body_len = @truncate(u31, sema.code.extra[extra_index]);
9967 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
9944 extra_index += 1;9968 extra_index += 1;
9945 const body = sema.code.extra[extra_index..][0..body_len];9969 const body = sema.code.extra[extra_index..][0..body_len];
9946 extra_index += body_len;9970 extra_index += body_len;
99479971
9948 const item = try sema.resolveInst(item_ref);9972 const item = try sema.resolveInst(item_ref);
9949 // Validation above ensured these will succeed.9973 // Validation above ensured these will succeed.
9950 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, undefined) catch unreachable;9974 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
9951 if (operand_val.eql(item_val, operand_ty, sema.mod)) {9975 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
9976 if (is_inline) child_block.inline_case_capture = operand;
9977
9952 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);9978 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
9953 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);9979 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
9954 }9980 }
...@@ -9962,6 +9988,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9962,6 +9988,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9962 const ranges_len = sema.code.extra[extra_index];9988 const ranges_len = sema.code.extra[extra_index];
9963 extra_index += 1;9989 extra_index += 1;
9964 const body_len = @truncate(u31, sema.code.extra[extra_index]);9990 const body_len = @truncate(u31, sema.code.extra[extra_index]);
9991 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
9965 extra_index += 1;9992 extra_index += 1;
9966 const items = sema.code.refSlice(extra_index, items_len);9993 const items = sema.code.refSlice(extra_index, items_len);
9967 extra_index += items_len;9994 extra_index += items_len;
...@@ -9970,8 +9997,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9970,8 +9997,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9970 for (items) |item_ref| {9997 for (items) |item_ref| {
9971 const item = try sema.resolveInst(item_ref);9998 const item = try sema.resolveInst(item_ref);
9972 // Validation above ensured these will succeed.9999 // Validation above ensured these will succeed.
9973 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, undefined) catch unreachable;10000 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
9974 if (operand_val.eql(item_val, operand_ty, sema.mod)) {10001 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
10002 if (is_inline) child_block.inline_case_capture = operand;
10003
9975 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);10004 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
9976 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);10005 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
9977 }10006 }
...@@ -9985,11 +10014,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9985,11 +10014,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9985 extra_index += 1;10014 extra_index += 1;
998610015
9987 // Validation above ensured these will succeed.10016 // Validation above ensured these will succeed.
9988 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, undefined) catch unreachable;10017 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable;
9989 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, undefined) catch unreachable;10018 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable;
9990 if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and10019 if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and
9991 (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty)))10020 (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty)))
9992 {10021 {
10022 if (is_inline) child_block.inline_case_capture = operand;
9993 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);10023 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
9994 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);10024 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
9995 }10025 }
...@@ -9999,6 +10029,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9999,6 +10029,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9999 }10029 }
10000 }10030 }
10001 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand);10031 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand);
10032 if (special.is_inline) child_block.inline_case_capture = operand;
10002 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);10033 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
10003 }10034 }
1000410035
...@@ -10060,7 +10091,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10060,7 +10091,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10060 // `item` is already guaranteed to be constant known.10091 // `item` is already guaranteed to be constant known.
1006110092
10062 const analyze_body = if (union_originally) blk: {10093 const analyze_body = if (union_originally) blk: {
10063 const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable;10094 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
10064 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);10095 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);
10065 break :blk field_ty.zigTypeTag() != .NoReturn;10096 break :blk field_ty.zigTypeTag() != .NoReturn;
10066 } else true;10097 } else true;
...@@ -10211,7 +10242,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10211,7 +10242,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10211 const analyze_body = if (union_originally)10242 const analyze_body = if (union_originally)
10212 for (items) |item_ref| {10243 for (items) |item_ref| {
10213 const item = try sema.resolveInst(item_ref);10244 const item = try sema.resolveInst(item_ref);
10214 const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable;10245 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
10215 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);10246 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);
10216 if (field_ty.zigTypeTag() != .NoReturn) break true;10247 if (field_ty.zigTypeTag() != .NoReturn) break true;
10217 } else false10248 } else false
...@@ -10606,7 +10637,7 @@ fn resolveSwitchItemVal(...@@ -10606,7 +10637,7 @@ fn resolveSwitchItemVal(
10606 // Constructing a LazySrcLoc is costly because we only have the switch AST node.10637 // Constructing a LazySrcLoc is costly because we only have the switch AST node.
10607 // Only if we know for sure we need to report a compile error do we resolve the10638 // Only if we know for sure we need to report a compile error do we resolve the
10608 // full source locations.10639 // full source locations.
10609 if (sema.resolveConstValue(block, .unneeded, item, undefined)) |val| {10640 if (sema.resolveConstValue(block, .unneeded, item, "")) |val| {
10610 return TypedValue{ .ty = item_ty, .val = val };10641 return TypedValue{ .ty = item_ty, .val = val };
10611 } else |err| switch (err) {10642 } else |err| switch (err) {
10612 error.NeededSourceLocation => {10643 error.NeededSourceLocation => {
...@@ -14291,6 +14322,38 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -14291,6 +14322,38 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
14291 const src = inst_data.src();14322 const src = inst_data.src();
14292 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };14323 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
14293 const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);14324 const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
14325 switch (operand_ty.zigTypeTag()) {
14326 .Fn,
14327 .NoReturn,
14328 .Undefined,
14329 .Null,
14330 .BoundFn,
14331 .Opaque,
14332 => return sema.fail(block, operand_src, "no size available for type '{}'", .{operand_ty.fmt(sema.mod)}),
14333
14334 .Type,
14335 .EnumLiteral,
14336 .ComptimeFloat,
14337 .ComptimeInt,
14338 .Void,
14339 => return sema.addIntUnsigned(Type.comptime_int, 0),
14340
14341 .Bool,
14342 .Int,
14343 .Float,
14344 .Pointer,
14345 .Array,
14346 .Struct,
14347 .Optional,
14348 .ErrorUnion,
14349 .ErrorSet,
14350 .Enum,
14351 .Union,
14352 .Vector,
14353 .Frame,
14354 .AnyFrame,
14355 => {},
14356 }
14294 const target = sema.mod.getTarget();14357 const target = sema.mod.getTarget();
14295 const bit_size = try operand_ty.bitSizeAdvanced(target, sema.kit(block, src));14358 const bit_size = try operand_ty.bitSizeAdvanced(target, sema.kit(block, src));
14296 return sema.addIntUnsigned(Type.comptime_int, bit_size);14359 return sema.addIntUnsigned(Type.comptime_int, bit_size);
...@@ -14321,7 +14384,7 @@ fn zirClosureCapture(...@@ -14321,7 +14384,7 @@ fn zirClosureCapture(
14321 // value only. In such case we preserve the type and use a dummy runtime value.14384 // value only. In such case we preserve the type and use a dummy runtime value.
14322 const operand = try sema.resolveInst(inst_data.operand);14385 const operand = try sema.resolveInst(inst_data.operand);
14323 const val = (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) orelse14386 const val = (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) orelse
14324 Value.initTag(.generic_poison);14387 Value.initTag(.unreachable_value);
1432514388
14326 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{14389 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{
14327 .ty = try sema.typeOf(operand).copy(sema.perm_arena),14390 .ty = try sema.typeOf(operand).copy(sema.perm_arena),
...@@ -14358,7 +14421,35 @@ fn zirClosureGet(...@@ -14358,7 +14421,35 @@ fn zirClosureGet(
14358 scope = scope.parent.?;14421 scope = scope.parent.?;
14359 } else unreachable;14422 } else unreachable;
1436014423
14361 if (tv.val.tag() == .generic_poison and !block.is_typeof and !block.is_comptime and sema.func != null) {14424 if (tv.val.tag() == .unreachable_value and !block.is_typeof and sema.func == null) {
14425 const msg = msg: {
14426 const name = name: {
14427 const file = sema.owner_decl.getFileScope();
14428 const tree = file.getTree(sema.mod.gpa) catch |err| {
14429 // In this case we emit a warning + a less precise source location.
14430 log.warn("unable to load {s}: {s}", .{
14431 file.sub_file_path, @errorName(err),
14432 });
14433 break :name null;
14434 };
14435 const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node);
14436 const token = tree.nodes.items(.main_token)[node];
14437 break :name tree.tokenSlice(token);
14438 };
14439
14440 const msg = if (name) |some|
14441 try sema.errMsg(block, inst_data.src(), "'{s}' not accessible outside function scope", .{some})
14442 else
14443 try sema.errMsg(block, inst_data.src(), "variable not accessible outside function scope", .{});
14444 errdefer msg.destroy(sema.gpa);
14445
14446 // TODO add "declared here" note
14447 break :msg msg;
14448 };
14449 return sema.failWithOwnedErrorMsg(msg);
14450 }
14451
14452 if (tv.val.tag() == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func != null) {
14362 const msg = msg: {14453 const msg = msg: {
14363 const name = name: {14454 const name = name: {
14364 const file = sema.owner_decl.getFileScope();14455 const file = sema.owner_decl.getFileScope();
...@@ -17121,7 +17212,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -17121,7 +17212,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17121 try sema.resolveTypeLayout(block, operand_src, operand_ty);17212 try sema.resolveTypeLayout(block, operand_src, operand_ty);
17122 const enum_ty = switch (operand_ty.zigTypeTag()) {17213 const enum_ty = switch (operand_ty.zigTypeTag()) {
17123 .EnumLiteral => {17214 .EnumLiteral => {
17124 const val = try sema.resolveConstValue(block, .unneeded, operand, undefined);17215 const val = try sema.resolveConstValue(block, .unneeded, operand, "");
17125 const bytes = val.castTag(.enum_literal).?.data;17216 const bytes = val.castTag(.enum_literal).?.data;
17126 return sema.addStrLit(block, bytes);17217 return sema.addStrLit(block, bytes);
17127 },17218 },
...@@ -18379,7 +18470,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -18379,7 +18470,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18379 return sema.failWithOwnedErrorMsg(msg);18470 return sema.failWithOwnedErrorMsg(msg);
18380 }18471 }
1838118472
18382 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| {18473 if (try sema.resolveMaybeUndefVal(block, operand_src, ptr)) |operand_val| {
18383 if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) {18474 if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) {
18384 return sema.failWithUseOfUndef(block, operand_src);18475 return sema.failWithUseOfUndef(block, operand_src);
18385 }18476 }
...@@ -18756,6 +18847,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -18756,6 +18847,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
18756 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);18847 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
18757 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);18848 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
1875818849
18850 if (ty.structFieldIsComptime(field_index)) {
18851 return sema.fail(block, src, "no offset available for comptime field", .{});
18852 }
18853
18759 switch (ty.containerLayout()) {18854 switch (ty.containerLayout()) {
18760 .Packed => {18855 .Packed => {
18761 var bit_sum: u64 = 0;18856 var bit_sum: u64 = 0;
...@@ -20096,7 +20191,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -20096,7 +20191,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
20096 var bound_arg_src: ?LazySrcLoc = null;20191 var bound_arg_src: ?LazySrcLoc = null;
20097 if (sema.typeOf(func).tag() == .bound_fn) {20192 if (sema.typeOf(func).tag() == .bound_fn) {
20098 bound_arg_src = func_src;20193 bound_arg_src = func_src;
20099 const bound_func = try sema.resolveValue(block, .unneeded, func, undefined);20194 const bound_func = try sema.resolveValue(block, .unneeded, func, "");
20100 const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;20195 const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
20101 func = bound_data.func_inst;20196 func = bound_data.func_inst;
20102 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount() + 1);20197 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount() + 1);
...@@ -20139,6 +20234,10 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -20139,6 +20234,10 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
20139 break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src);20234 break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src);
20140 } else try sema.structFieldIndex(block, struct_ty, field_name, name_src);20235 } else try sema.structFieldIndex(block, struct_ty, field_name, name_src);
2014120236
20237 if (struct_ty.structFieldIsComptime(field_index)) {
20238 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
20239 }
20240
20142 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);20241 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);
20143 const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;20242 const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;
2014420243
...@@ -21197,6 +21296,8 @@ const ExternPosition = enum {...@@ -21197,6 +21296,8 @@ const ExternPosition = enum {
21197 ret_ty,21296 ret_ty,
21198 param_ty,21297 param_ty,
21199 union_field,21298 union_field,
21299 struct_field,
21300 element,
21200 other,21301 other,
21201};21302};
2120221303
...@@ -21234,7 +21335,10 @@ fn validateExternType(...@@ -21234,7 +21335,10 @@ fn validateExternType(
21234 8, 16, 32, 64, 128 => return true,21335 8, 16, 32, 64, 128 => return true,
21235 else => return false,21336 else => return false,
21236 },21337 },
21237 .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()),21338 .Fn => {
21339 if (position != .other) return false;
21340 return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention());
21341 },
21238 .Enum => {21342 .Enum => {
21239 var buf: Type.Payload.Bits = undefined;21343 var buf: Type.Payload.Bits = undefined;
21240 return sema.validateExternType(block, src, ty.intTagType(&buf), position);21344 return sema.validateExternType(block, src, ty.intTagType(&buf), position);
...@@ -21253,9 +21357,9 @@ fn validateExternType(...@@ -21253,9 +21357,9 @@ fn validateExternType(
21253 },21357 },
21254 .Array => {21358 .Array => {
21255 if (position == .ret_ty or position == .param_ty) return false;21359 if (position == .ret_ty or position == .param_ty) return false;
21256 return sema.validateExternType(block, src, ty.elemType2(), .other);21360 return sema.validateExternType(block, src, ty.elemType2(), .element);
21257 },21361 },
21258 .Vector => return sema.validateExternType(block, src, ty.elemType2(), .other),21362 .Vector => return sema.validateExternType(block, src, ty.elemType2(), .element),
21259 .Optional => return ty.isPtrLikeOptional(),21363 .Optional => return ty.isPtrLikeOptional(),
21260 }21364 }
21261}21365}
...@@ -21295,11 +21399,18 @@ fn explainWhyTypeIsNotExtern(...@@ -21295,11 +21399,18 @@ fn explainWhyTypeIsNotExtern(
21295 } else {21399 } else {
21296 try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{});21400 try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{});
21297 },21401 },
21298 .Fn => switch (ty.fnCallingConvention()) {21402 .Fn => {
21299 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),21403 if (position != .other) {
21300 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),21404 try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{});
21301 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),21405 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
21302 else => return,21406 return;
21407 }
21408 switch (ty.fnCallingConvention()) {
21409 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),
21410 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),
21411 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),
21412 else => return,
21413 }
21303 },21414 },
21304 .Enum => {21415 .Enum => {
21305 var buf: Type.Payload.Bits = undefined;21416 var buf: Type.Payload.Bits = undefined;
...@@ -21315,9 +21426,9 @@ fn explainWhyTypeIsNotExtern(...@@ -21315,9 +21426,9 @@ fn explainWhyTypeIsNotExtern(
21315 } else if (position == .param_ty) {21426 } else if (position == .param_ty) {
21316 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});21427 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
21317 }21428 }
21318 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position);21429 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element);
21319 },21430 },
21320 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position),21431 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element),
21321 .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),21432 .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
21322 }21433 }
21323}21434}
...@@ -22047,7 +22158,7 @@ fn fieldPtr(...@@ -22047,7 +22158,7 @@ fn fieldPtr(
22047 }22158 }
22048 },22159 },
22049 .Type => {22160 .Type => {
22050 _ = try sema.resolveConstValue(block, .unneeded, object_ptr, undefined);22161 _ = try sema.resolveConstValue(block, .unneeded, object_ptr, "");
22051 const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src);22162 const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src);
22052 const inner = if (is_pointer_to)22163 const inner = if (is_pointer_to)
22053 try sema.analyzeLoad(block, src, result, object_ptr_src)22164 try sema.analyzeLoad(block, src, result, object_ptr_src)
...@@ -23375,7 +23486,7 @@ fn coerceExtra(...@@ -23375,7 +23486,7 @@ fn coerceExtra(
2337523486
23376 // Function body to function pointer.23487 // Function body to function pointer.
23377 if (inst_ty.zigTypeTag() == .Fn) {23488 if (inst_ty.zigTypeTag() == .Fn) {
23378 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined);23489 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
23379 const fn_decl = fn_val.pointerDecl().?;23490 const fn_decl = fn_val.pointerDecl().?;
23380 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);23491 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
23381 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);23492 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
...@@ -23677,7 +23788,7 @@ fn coerceExtra(...@@ -23677,7 +23788,7 @@ fn coerceExtra(
23677 },23788 },
23678 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {23789 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {
23679 .ComptimeFloat => {23790 .ComptimeFloat => {
23680 const val = try sema.resolveConstValue(block, .unneeded, inst, undefined);23791 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
23681 const result_val = try val.floatCast(sema.arena, dest_ty, target);23792 const result_val = try val.floatCast(sema.arena, dest_ty, target);
23682 return try sema.addConstant(dest_ty, result_val);23793 return try sema.addConstant(dest_ty, result_val);
23683 },23794 },
...@@ -23735,7 +23846,7 @@ fn coerceExtra(...@@ -23735,7 +23846,7 @@ fn coerceExtra(
23735 .Enum => switch (inst_ty.zigTypeTag()) {23846 .Enum => switch (inst_ty.zigTypeTag()) {
23736 .EnumLiteral => {23847 .EnumLiteral => {
23737 // enum literal to enum23848 // enum literal to enum
23738 const val = try sema.resolveConstValue(block, .unneeded, inst, undefined);23849 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
23739 const bytes = val.castTag(.enum_literal).?.data;23850 const bytes = val.castTag(.enum_literal).?.data;
23740 const field_index = dest_ty.enumFieldIndex(bytes) orelse {23851 const field_index = dest_ty.enumFieldIndex(bytes) orelse {
23741 const msg = msg: {23852 const msg = msg: {
...@@ -24805,7 +24916,7 @@ fn coerceVarArgParam(...@@ -24805,7 +24916,7 @@ fn coerceVarArgParam(
24805 .{},24916 .{},
24806 ),24917 ),
24807 .Fn => blk: {24918 .Fn => blk: {
24808 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined);24919 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
24809 const fn_decl = fn_val.pointerDecl().?;24920 const fn_decl = fn_val.pointerDecl().?;
24810 break :blk try sema.analyzeDeclRef(fn_decl);24921 break :blk try sema.analyzeDeclRef(fn_decl);
24811 },24922 },
...@@ -24814,13 +24925,13 @@ fn coerceVarArgParam(...@@ -24814,13 +24925,13 @@ fn coerceVarArgParam(
24814 };24925 };
2481524926
24816 const coerced_ty = sema.typeOf(coerced);24927 const coerced_ty = sema.typeOf(coerced);
24817 if (!try sema.validateExternType(block, inst_src, coerced_ty, .other)) {24928 if (!try sema.validateExternType(block, inst_src, coerced_ty, .param_ty)) {
24818 const msg = msg: {24929 const msg = msg: {
24819 const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)});24930 const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)});
24820 errdefer msg.destroy(sema.gpa);24931 errdefer msg.destroy(sema.gpa);
2482124932
24822 const src_decl = sema.mod.declPtr(block.src_decl);24933 const src_decl = sema.mod.declPtr(block.src_decl);
24823 try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl), coerced_ty, .other);24934 try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl), coerced_ty, .param_ty);
2482424935
24825 try sema.addDeclaredHereNote(msg, coerced_ty);24936 try sema.addDeclaredHereNote(msg, coerced_ty);
24826 break :msg msg;24937 break :msg msg;
...@@ -26904,10 +27015,14 @@ fn analyzeIsNull(...@@ -26904,10 +27015,14 @@ fn analyzeIsNull(
26904 }27015 }
26905 }27016 }
2690627017
27018 const inverted_non_null_res = if (invert_logic) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
26907 const operand_ty = sema.typeOf(operand);27019 const operand_ty = sema.typeOf(operand);
26908 var buf: Type.Payload.ElemType = undefined;27020 var buf: Type.Payload.ElemType = undefined;
26909 if (operand_ty.zigTypeTag() == .Optional and operand_ty.optionalChild(&buf).zigTypeTag() == .NoReturn) {27021 if (operand_ty.zigTypeTag() == .Optional and operand_ty.optionalChild(&buf).zigTypeTag() == .NoReturn) {
26910 return Air.Inst.Ref.bool_true;27022 return inverted_non_null_res;
27023 }
27024 if (operand_ty.zigTypeTag() != .Optional and !operand_ty.isPtrLikeOptional()) {
27025 return inverted_non_null_res;
26911 }27026 }
26912 try sema.requireRuntimeBlock(block, src, null);27027 try sema.requireRuntimeBlock(block, src, null);
26913 const air_tag: Air.Inst.Tag = if (invert_logic) .is_non_null else .is_null;27028 const air_tag: Air.Inst.Tag = if (invert_logic) .is_non_null else .is_null;
...@@ -29105,14 +29220,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -29105,14 +29220,14 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
29105 };29220 };
29106 return sema.failWithOwnedErrorMsg(msg);29221 return sema.failWithOwnedErrorMsg(msg);
29107 }29222 }
29108 if (struct_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field.ty, .other)) {29223 if (struct_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field.ty, .struct_field)) {
29109 const msg = msg: {29224 const msg = msg: {
29110 const tree = try sema.getAstTree(&block_scope);29225 const tree = try sema.getAstTree(&block_scope);
29111 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);29226 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);
29112 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});29227 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
29113 errdefer msg.destroy(sema.gpa);29228 errdefer msg.destroy(sema.gpa);
2911429229
29115 try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other);29230 try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .struct_field);
2911629231
29117 try sema.addDeclaredHereNote(msg, field.ty);29232 try sema.addDeclaredHereNote(msg, field.ty);
29118 break :msg msg;29233 break :msg msg;
src/Zir.zig+11-7
...@@ -402,6 +402,8 @@ pub const Inst = struct {...@@ -402,6 +402,8 @@ pub const Inst = struct {
402 /// Emits a compile error if an error is ignored.402 /// Emits a compile error if an error is ignored.
403 /// Uses the `un_node` field.403 /// Uses the `un_node` field.
404 ensure_result_non_error,404 ensure_result_non_error,
405 /// Emits a compile error error union payload is not void.
406 ensure_err_union_payload_void,
405 /// Create a `E!T` type.407 /// Create a `E!T` type.
406 /// Uses the `pl_node` field with `Bin` payload.408 /// Uses the `pl_node` field with `Bin` payload.
407 error_union_type,409 error_union_type,
...@@ -646,9 +648,6 @@ pub const Inst = struct {...@@ -646,9 +648,6 @@ pub const Inst = struct {
646 /// Given a pointer to an error union value, returns the error code. No safety checks.648 /// Given a pointer to an error union value, returns the error code. No safety checks.
647 /// Uses the `un_node` field.649 /// Uses the `un_node` field.
648 err_union_code_ptr,650 err_union_code_ptr,
649 /// Takes a *E!T and raises a compiler error if T != void
650 /// Uses the `un_tok` field.
651 ensure_err_payload_void,
652 /// An enum literal. Uses the `str_tok` union field.651 /// An enum literal. Uses the `str_tok` union field.
653 enum_literal,652 enum_literal,
654 /// A switch expression. Uses the `pl_node` union field.653 /// A switch expression. Uses the `pl_node` union field.
...@@ -1060,6 +1059,7 @@ pub const Inst = struct {...@@ -1060,6 +1059,7 @@ pub const Inst = struct {
1060 .elem_val_node,1059 .elem_val_node,
1061 .ensure_result_used,1060 .ensure_result_used,
1062 .ensure_result_non_error,1061 .ensure_result_non_error,
1062 .ensure_err_union_payload_void,
1063 .@"export",1063 .@"export",
1064 .export_value,1064 .export_value,
1065 .field_ptr,1065 .field_ptr,
...@@ -1113,7 +1113,6 @@ pub const Inst = struct {...@@ -1113,7 +1113,6 @@ pub const Inst = struct {
1113 .err_union_code_ptr,1113 .err_union_code_ptr,
1114 .ptr_type,1114 .ptr_type,
1115 .overflow_arithmetic_ptr,1115 .overflow_arithmetic_ptr,
1116 .ensure_err_payload_void,
1117 .enum_literal,1116 .enum_literal,
1118 .merge_error_sets,1117 .merge_error_sets,
1119 .error_union_type,1118 .error_union_type,
...@@ -1282,7 +1281,7 @@ pub const Inst = struct {...@@ -1282,7 +1281,7 @@ pub const Inst = struct {
1282 .dbg_block_end,1281 .dbg_block_end,
1283 .ensure_result_used,1282 .ensure_result_used,
1284 .ensure_result_non_error,1283 .ensure_result_non_error,
1285 .ensure_err_payload_void,1284 .ensure_err_union_payload_void,
1286 .set_eval_branch_quota,1285 .set_eval_branch_quota,
1287 .atomic_store,1286 .atomic_store,
1288 .store,1287 .store,
...@@ -1615,6 +1614,7 @@ pub const Inst = struct {...@@ -1615,6 +1614,7 @@ pub const Inst = struct {
1615 .elem_val_node = .pl_node,1614 .elem_val_node = .pl_node,
1616 .ensure_result_used = .un_node,1615 .ensure_result_used = .un_node,
1617 .ensure_result_non_error = .un_node,1616 .ensure_result_non_error = .un_node,
1617 .ensure_err_union_payload_void = .un_node,
1618 .error_union_type = .pl_node,1618 .error_union_type = .pl_node,
1619 .error_value = .str_tok,1619 .error_value = .str_tok,
1620 .@"export" = .pl_node,1620 .@"export" = .pl_node,
...@@ -1677,7 +1677,6 @@ pub const Inst = struct {...@@ -1677,7 +1677,6 @@ pub const Inst = struct {
1677 .err_union_payload_unsafe_ptr = .un_node,1677 .err_union_payload_unsafe_ptr = .un_node,
1678 .err_union_code = .un_node,1678 .err_union_code = .un_node,
1679 .err_union_code_ptr = .un_node,1679 .err_union_code_ptr = .un_node,
1680 .ensure_err_payload_void = .un_tok,
1681 .enum_literal = .str_tok,1680 .enum_literal = .str_tok,
1682 .switch_block = .pl_node,1681 .switch_block = .pl_node,
1683 .switch_cond = .un_node,1682 .switch_cond = .un_node,
...@@ -3051,11 +3050,16 @@ pub const Inst = struct {...@@ -3051,11 +3050,16 @@ pub const Inst = struct {
3051 var multi_i: u32 = 0;3050 var multi_i: u32 = 0;
3052 while (true) : (multi_i += 1) {3051 while (true) : (multi_i += 1) {
3053 const items_len = zir.extra[extra_index];3052 const items_len = zir.extra[extra_index];
3054 extra_index += 2;3053 extra_index += 1;
3054 const ranges_len = zir.extra[extra_index];
3055 extra_index += 1;
3055 const body_len = @truncate(u31, zir.extra[extra_index]);3056 const body_len = @truncate(u31, zir.extra[extra_index]);
3056 extra_index += 1;3057 extra_index += 1;
3057 const items = zir.refSlice(extra_index, items_len);3058 const items = zir.refSlice(extra_index, items_len);
3058 extra_index += items_len;3059 extra_index += items_len;
3060 // Each range has a start and an end.
3061 extra_index += 2 * ranges_len;
3062
3059 const body = zir.extra[extra_index..][0..body_len];3063 const body = zir.extra[extra_index..][0..body_len];
3060 extra_index += body_len;3064 extra_index += body_len;
30613065
src/print_zir.zig+1-1
...@@ -162,6 +162,7 @@ const Writer = struct {...@@ -162,6 +162,7 @@ const Writer = struct {
162 .load,162 .load,
163 .ensure_result_used,163 .ensure_result_used,
164 .ensure_result_non_error,164 .ensure_result_non_error,
165 .ensure_err_union_payload_void,
165 .ret_node,166 .ret_node,
166 .ret_load,167 .ret_load,
167 .resolve_inferred_alloc,168 .resolve_inferred_alloc,
...@@ -235,7 +236,6 @@ const Writer = struct {...@@ -235,7 +236,6 @@ const Writer = struct {
235236
236 .ref,237 .ref,
237 .ret_tok,238 .ret_tok,
238 .ensure_err_payload_void,
239 .closure_capture,239 .closure_capture,
240 .switch_capture_tag,240 .switch_capture_tag,
241 => try self.writeUnTok(stream, inst),241 => try self.writeUnTok(stream, inst),
src/type.zig+22
...@@ -5664,6 +5664,28 @@ pub const Type = extern union {...@@ -5664,6 +5664,28 @@ pub const Type = extern union {
5664 }5664 }
5665 }5665 }
56665666
5667 pub fn structFieldIsComptime(ty: Type, index: usize) bool {
5668 switch (ty.tag()) {
5669 .@"struct" => {
5670 const struct_obj = ty.castTag(.@"struct").?.data;
5671 if (struct_obj.layout == .Packed) return false;
5672 const field = struct_obj.fields.values()[index];
5673 return field.is_comptime;
5674 },
5675 .tuple => {
5676 const tuple = ty.castTag(.tuple).?.data;
5677 const val = tuple.values[index];
5678 return val.tag() != .unreachable_value;
5679 },
5680 .anon_struct => {
5681 const anon_struct = ty.castTag(.anon_struct).?.data;
5682 const val = anon_struct.values[index];
5683 return val.tag() != .unreachable_value;
5684 },
5685 else => unreachable,
5686 }
5687 }
5688
5667 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 {5689 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 {
5668 const struct_obj = ty.castTag(.@"struct").?.data;5690 const struct_obj = ty.castTag(.@"struct").?.data;
5669 assert(struct_obj.layout == .Packed);5691 assert(struct_obj.layout == .Packed);
test/behavior.zig+1
...@@ -95,6 +95,7 @@ test {...@@ -95,6 +95,7 @@ test {
95 _ = @import("behavior/bugs/12801-1.zig");95 _ = @import("behavior/bugs/12801-1.zig");
96 _ = @import("behavior/bugs/12801-2.zig");96 _ = @import("behavior/bugs/12801-2.zig");
97 _ = @import("behavior/bugs/12885.zig");97 _ = @import("behavior/bugs/12885.zig");
98 _ = @import("behavior/bugs/12890.zig");
98 _ = @import("behavior/bugs/12911.zig");99 _ = @import("behavior/bugs/12911.zig");
99 _ = @import("behavior/bugs/12928.zig");100 _ = @import("behavior/bugs/12928.zig");
100 _ = @import("behavior/bugs/12945.zig");101 _ = @import("behavior/bugs/12945.zig");
test/behavior/bugs/12890.zig created+18
...@@ -0,0 +1,18 @@
1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");
3
4fn a(b: []u3, c: u3) void {
5 switch (c) {
6 0...1 => b[c] = c,
7 2...3 => b[c] = c,
8 4...7 => |d| b[d] = c,
9 }
10}
11test {
12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14
15 var arr: [8]u3 = undefined;
16 a(&arr, 5);
17 try expect(arr[5] == 5);
18}
test/behavior/error.zig+1-1
...@@ -7,7 +7,7 @@ const mem = std.mem;...@@ -7,7 +7,7 @@ const mem = std.mem;
7/// A more basic implementation of std.testing.expectError which7/// A more basic implementation of std.testing.expectError which
8/// does not require formatter/printing support8/// does not require formatter/printing support
9fn expectError(expected_err: anyerror, observed_err_union: anytype) !void {9fn expectError(expected_err: anyerror, observed_err_union: anytype) !void {
10 if (observed_err_union) {10 if (observed_err_union) |_| {
11 return error.TestExpectedError;11 return error.TestExpectedError;
12 } else |err| if (err == expected_err) {12 } else |err| if (err == expected_err) {
13 return; // Success13 return; // Success
test/behavior/eval.zig+14
...@@ -1398,3 +1398,17 @@ test "continue in inline for inside a comptime switch" {...@@ -1398,3 +1398,17 @@ test "continue in inline for inside a comptime switch" {
1398 }1398 }
1399 try expect(count == 4);1399 try expect(count == 4);
1400}1400}
1401
1402test "continue nested inline for loop" {
1403 var a: u8 = 0;
1404 loop: inline for ([_]u8{ 1, 2 }) |x| {
1405 inline for ([_]u8{1}) |y| {
1406 if (x == y) {
1407 continue :loop;
1408 }
1409 }
1410 a = x;
1411 try expect(x == 2);
1412 }
1413 try expect(a == 2);
1414}
test/behavior/inline_switch.zig+13
...@@ -129,3 +129,16 @@ test "inline else int all values" {...@@ -129,3 +129,16 @@ test "inline else int all values" {
129 },129 },
130 }130 }
131}131}
132
133test "inline switch capture is set when switch operand is comptime known" {
134 const U2 = union(enum) {
135 a: u32,
136 };
137 var u: U2 = undefined;
138 switch (u) {
139 inline else => |*f, tag| {
140 try expect(@TypeOf(f) == *u32);
141 try expect(tag == .a);
142 },
143 }
144}
test/behavior/pointers.zig+11
...@@ -483,3 +483,14 @@ test "pointer to constant decl preserves alignment" {...@@ -483,3 +483,14 @@ test "pointer to constant decl preserves alignment" {
483 const alignment = @typeInfo(@TypeOf(&S.aligned)).Pointer.alignment;483 const alignment = @typeInfo(@TypeOf(&S.aligned)).Pointer.alignment;
484 try std.testing.expect(alignment == 8);484 try std.testing.expect(alignment == 8);
485}485}
486
487test "ptrCast comptime known slice to C pointer" {
488 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
489 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
492
493 const s: [:0]const u8 = "foo";
494 var p = @ptrCast([*c]const u8, s);
495 try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0));
496}
test/behavior/sizeof_and_typeof.zig+4
...@@ -310,3 +310,7 @@ test "lazy size cast to float" {...@@ -310,3 +310,7 @@ test "lazy size cast to float" {
310 try expect(@as(f32, @sizeOf(S)) == 1.0);310 try expect(@as(f32, @sizeOf(S)) == 1.0);
311 }311 }
312}312}
313
314test "bitSizeOf comptime_int" {
315 try expect(@bitSizeOf(comptime_int) == 0);
316}
test/cases/compile_errors/accessing_runtime_paramter_outside_function_scope.zig created+12
...@@ -0,0 +1,12 @@
1export fn entry(y: u8) void {
2 const Thing = struct {
3 y: u8 = y,
4 };
5 _ = @sizeOf(Thing);
6}
7
8// error
9// backend=stage2
10// target=native
11//
12// :3:17: error: 'y' not accessible outside function scope
test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig created+16
...@@ -0,0 +1,16 @@
1const T = struct {
2 comptime a: u32 = 2,
3};
4pub export fn entry1() void {
5 @offsetOf(T, "a");
6}
7pub export fn entry2() void {
8 @fieldParentPtr(T, "a", undefined);
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :5:5: error: no offset available for comptime field
16// :8:5: error: cannot get @fieldParentPtr of a comptime field
test/cases/compile_errors/generic_funciton_instantiation_inherits_parent_branch_quota.zig created+30
...@@ -0,0 +1,30 @@
1pub export fn entry1() void {
2 @setEvalBranchQuota(1001);
3 // Return type evaluation should inherit both the
4 // parent's branch quota and count meaning
5 // at least 2002 backwards branches are required.
6 comptime var i = 0;
7 inline while (i < 1000) : (i += 1) {}
8 _ = simple(10);
9}
10pub export fn entry2() void {
11 @setEvalBranchQuota(2001);
12 comptime var i = 0;
13 inline while (i < 1000) : (i += 1) {}
14 _ = simple(10);
15}
16fn simple(comptime n: usize) Type(n) {
17 return n;
18}
19fn Type(comptime n: usize) type {
20 if (n <= 1) return usize;
21 return Type(n - 1);
22}
23
24// error
25// backend=stage2
26// target=native
27//
28// :21:16: error: evaluation exceeded 1001 backwards branches
29// :21:16: note: use @setEvalBranchQuota() to raise the branch limit from 1001
30// :16:34: note: called from here
test/cases/compile_errors/non_void_error_union_payload_ignored.zig created+25
...@@ -0,0 +1,25 @@
1pub export fn entry1() void {
2 var x: anyerror!usize = 5;
3 if (x) {
4 // foo
5 } else |_| {
6 // bar
7 }
8}
9pub export fn entry2() void {
10 var x: anyerror!usize = 5;
11 while (x) {
12 // foo
13 } else |_| {
14 // bar
15 }
16}
17
18// error
19// backend=stage2
20// target=native
21//
22// :3:5: error: error union payload is ignored
23// :3:5: note: payload value can be explicitly ignored with '|_|'
24// :11:5: error: error union payload is ignored
25// :11:5: note: payload value can be explicitly ignored with '|_|'
test/cases/compile_errors/old_fn_ptr_in_extern_context.zig created+20
...@@ -0,0 +1,20 @@
1const S = extern struct {
2 a: fn () callconv(.C) void,
3};
4comptime {
5 _ = @sizeOf(S) == 1;
6}
7comptime {
8 _ = [*c][4]fn() callconv(.C) void;
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :2:5: error: extern structs cannot contain fields of type 'fn() callconv(.C) void'
16// :2:5: note: type has no guaranteed in-memory representation
17// :2:5: note: use '*const ' to make a function pointer type
18// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn() callconv(.C) void'
19// :8:13: note: type has no guaranteed in-memory representation
20// :8:13: note: use '*const ' to make a function pointer type
test/cases/compile_errors/sema_src_used_after_inline_call.zig created+26
...@@ -0,0 +1,26 @@
1inline fn bit_count(value: i32) i32 {
2 var i = value;
3 // Algo from : http://aggregate.ee.engr.uky.edu/MAGIC/#Population%20Count%20(ones%20Count)
4 i -= ((i >> 1) & 0x55555555);
5 i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
6 i = (((i >> 4) + i) & 0x0F0F0F0F);
7 i += (i >> 8);
8 i += (i >> 16);
9 return (i & 0x0000003F);
10}
11
12inline fn number_of_trailing_zeros(i: i32) u32 {
13 return @as(u32, bit_count((i & -i) - 1));
14}
15
16export fn entry() void {
17 _ = number_of_trailing_zeros(0);
18}
19
20// error
21// backend=stage2
22// target=native
23//
24// :13:30: error: expected type 'u32', found 'i32'
25// :13:30: note: unsigned 32-bit int cannot represent all possible signed 32-bit values
26// :17:33: note: called from here
test/cases/compile_errors/stage1/obj/runtime_value_in_switch_prong.zig created+14
...@@ -0,0 +1,14 @@
1pub export fn entry() void {
2 var byte: u8 = 1;
3 switch (byte) {
4 byte => {},
5 else => {},
6 }
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :4:9: error: unable to resolve comptime value
14// :4:9: note: switch prong values must be comptime known