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
25062506 .dbg_block_end,
25072507 .ensure_result_used,
25082508 .ensure_result_non_error,
2509 .ensure_err_union_payload_void,
25092510 .@"export",
25102511 .export_value,
25112512 .set_eval_branch_quota,
2512 .ensure_err_payload_void,
25132513 .atomic_store,
25142514 .store,
25152515 .store_node,
......@@ -5499,6 +5499,7 @@ fn ifExpr(
54995499 try then_scope.addDbgVar(.dbg_var_val, ident_name, payload_inst);
55005500 break :s &payload_val_scope.base;
55015501 } else {
5502 _ = try then_scope.addUnNode(.ensure_err_union_payload_void, cond.inst, node);
55025503 break :s &then_scope.base;
55035504 }
55045505 } else if (if_full.payload_token) |payload_token| {
......@@ -5836,6 +5837,7 @@ fn whileExpr(
58365837 dbg_var_inst = indexToRef(payload_inst);
58375838 break :s &payload_val_scope.base;
58385839 } else {
5840 _ = try then_scope.addUnNode(.ensure_err_union_payload_void, cond.inst, node);
58395841 break :s &then_scope.base;
58405842 }
58415843 } else if (while_full.payload_token) |payload_token| {
src/Sema.zig+182-67
......@@ -1034,8 +1034,8 @@ fn analyzeBodyInner(
10341034 i += 1;
10351035 continue;
10361036 },
1037 .ensure_err_payload_void => {
1038 try sema.zirEnsureErrPayloadVoid(block, inst);
1037 .ensure_err_union_payload_void => {
1038 try sema.zirEnsureErrUnionPayloadVoid(block, inst);
10391039 i += 1;
10401040 continue;
10411041 },
......@@ -1302,17 +1302,28 @@ fn analyzeBodyInner(
13021302 // current list of parameters and restore it later.
13031303 // Note: this probably needs to be resolved in a more general manner.
13041304 const prev_params = block.params;
1305 const prev_inline_block = block.inline_block;
1306 if (tags[inline_body[inline_body.len - 1]] == .repeat_inline) {
1307 block.inline_block = inline_body[0];
1305 const need_sub_block = tags[inline_body[inline_body.len - 1]] == .repeat_inline;
1306 var sub_block = block;
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;
13081315 }
13091316 block.params = .{};
13101317 defer {
13111318 block.params.deinit(gpa);
13121319 block.params = prev_params;
1313 block.inline_block = prev_inline_block;
1320 block_space.instructions.deinit(gpa);
13141321 }
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
13161327 // A runtime conditional branch that needs a post-hoc block to be
13171328 // emitted communicates this by mapping the block index into the inst map.
13181329 if (map.get(inst)) |new_block_ref| ph: {
......@@ -2469,7 +2480,7 @@ fn createAnonymousDeclTypeNamed(
24692480 const arg = sema.inst_map.get(zir_inst).?;
24702481 // The comptime call code in analyzeCall already did this, so we're
24712482 // 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
24742485 if (arg_i != 0) try buf.appendSlice(",");
24752486 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
30893100 }
30903101}
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
30923130fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
30933131 const tracy = trace(@src());
30943132 defer tracy.end();
......@@ -5631,7 +5669,7 @@ fn zirCall(
56315669 var bound_arg_src: ?LazySrcLoc = null;
56325670 if (func_type.tag() == .bound_fn) {
56335671 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, "");
56355673 const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
56365674 func = bound_data.func_inst;
56375675 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len + 1);
......@@ -6010,6 +6048,7 @@ fn analyzeCall(
60106048 const parent_inst_map = sema.inst_map;
60116049 sema.inst_map = .{};
60126050 defer {
6051 sema.src = call_src;
60136052 sema.inst_map.deinit(gpa);
60146053 sema.inst_map = parent_inst_map;
60156054 }
......@@ -6213,7 +6252,7 @@ fn analyzeCall(
62136252 }
62146253
62156254 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
62186257 // TODO: check whether any external comptime memory was mutated by the
62196258 // comptime function call. If so, then do not memoize the call here.
......@@ -6675,6 +6714,8 @@ fn instantiateGenericCall(
66756714 .comptime_args_fn_inst = module_fn.zir_body_inst,
66766715 .preallocated_new_func = new_module_func,
66776716 .is_generic_instantiation = true,
6717 .branch_quota = sema.branch_quota,
6718 .branch_count = sema.branch_count,
66786719 };
66796720 defer child_sema.deinit();
66806721
......@@ -6724,12 +6765,12 @@ fn instantiateGenericCall(
67246765 const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val);
67256766 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
67266767 } else {
6727 return sema.failWithNeededComptime(block, .unneeded, undefined);
6768 return sema.failWithNeededComptime(block, .unneeded, "");
67286769 }
67296770 } else if (is_anytype) {
67306771 const arg_ty = sema.typeOf(arg);
67316772 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, "");
67336774 const child_arg = try child_sema.addConstant(arg_ty, arg_val);
67346775 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
67356776 } else {
......@@ -6751,7 +6792,7 @@ fn instantiateGenericCall(
67516792 }
67526793 return err;
67536794 };
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;
67556796 const new_func = new_func_val.castTag(.function).?.data;
67566797 errdefer new_func.deinit(gpa);
67576798 assert(new_func == new_module_func);
......@@ -7674,24 +7715,6 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
76747715 return block.addTyOp(.unwrap_errunion_err_ptr, result_ty, operand);
76757716}
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
76957718fn zirFunc(
76967719 sema: *Sema,
76977720 block: *Block,
......@@ -9119,7 +9142,7 @@ fn zirSwitchCapture(
91199142 const union_obj = operand_ty.cast(Type.Payload.Union).?.data;
91209143 const first_item = try sema.resolveInst(items[0]);
91219144 // 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
91249147 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, sema.mod).?);
91259148 const first_field = union_obj.fields.values()[first_field_index];
......@@ -9127,7 +9150,7 @@ fn zirSwitchCapture(
91279150 for (items[1..]) |item, i| {
91289151 const item_ref = try sema.resolveInst(item);
91299152 // 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
91329155 const field_index = operand_ty.unionTagFieldIndex(item_val, sema.mod).?;
91339156 const field = union_obj.fields.values()[field_index];
......@@ -9188,7 +9211,7 @@ fn zirSwitchCapture(
91889211 for (items) |item| {
91899212 const item_ref = try sema.resolveInst(item);
91909213 // 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;
91929215 names.putAssumeCapacityNoClobber(
91939216 item_val.getError().?,
91949217 {},
......@@ -9202,7 +9225,7 @@ fn zirSwitchCapture(
92029225 } else {
92039226 const item_ref = try sema.resolveInst(items[0]);
92049227 // 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
92079230 const item_ty = try Type.Tag.error_set_single.create(sema.arena, item_val.getError().?);
92089231 return sema.bitCast(block, item_ty, operand, operand_src);
......@@ -9941,14 +9964,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
99419964 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
99429965 extra_index += 1;
99439966 const body_len = @truncate(u31, sema.code.extra[extra_index]);
9967 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
99449968 extra_index += 1;
99459969 const body = sema.code.extra[extra_index..][0..body_len];
99469970 extra_index += body_len;
99479971
99489972 const item = try sema.resolveInst(item_ref);
99499973 // 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;
99519975 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
9976 if (is_inline) child_block.inline_case_capture = operand;
9977
99529978 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
99539979 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
99549980 }
......@@ -9962,6 +9988,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
99629988 const ranges_len = sema.code.extra[extra_index];
99639989 extra_index += 1;
99649990 const body_len = @truncate(u31, sema.code.extra[extra_index]);
9991 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
99659992 extra_index += 1;
99669993 const items = sema.code.refSlice(extra_index, items_len);
99679994 extra_index += items_len;
......@@ -9970,8 +9997,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
99709997 for (items) |item_ref| {
99719998 const item = try sema.resolveInst(item_ref);
99729999 // 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;
997410001 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
10002 if (is_inline) child_block.inline_case_capture = operand;
10003
997510004 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
997610005 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
997710006 }
......@@ -9985,11 +10014,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
998510014 extra_index += 1;
998610015
998710016 // Validation above ensured these will succeed.
9988 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, undefined) catch unreachable;
9989 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, undefined) catch unreachable;
10017 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable;
10018 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable;
999010019 if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and
999110020 (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty)))
999210021 {
10022 if (is_inline) child_block.inline_case_capture = operand;
999310023 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
999410024 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
999510025 }
......@@ -9999,6 +10029,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
999910029 }
1000010030 }
1000110031 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand);
10032 if (special.is_inline) child_block.inline_case_capture = operand;
1000210033 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
1000310034 }
1000410035
......@@ -10060,7 +10091,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1006010091 // `item` is already guaranteed to be constant known.
1006110092
1006210093 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;
1006410095 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);
1006510096 break :blk field_ty.zigTypeTag() != .NoReturn;
1006610097 } else true;
......@@ -10211,7 +10242,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1021110242 const analyze_body = if (union_originally)
1021210243 for (items) |item_ref| {
1021310244 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;
1021510246 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);
1021610247 if (field_ty.zigTypeTag() != .NoReturn) break true;
1021710248 } else false
......@@ -10606,7 +10637,7 @@ fn resolveSwitchItemVal(
1060610637 // Constructing a LazySrcLoc is costly because we only have the switch AST node.
1060710638 // Only if we know for sure we need to report a compile error do we resolve the
1060810639 // full source locations.
10609 if (sema.resolveConstValue(block, .unneeded, item, undefined)) |val| {
10640 if (sema.resolveConstValue(block, .unneeded, item, "")) |val| {
1061010641 return TypedValue{ .ty = item_ty, .val = val };
1061110642 } else |err| switch (err) {
1061210643 error.NeededSourceLocation => {
......@@ -14291,6 +14322,38 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1429114322 const src = inst_data.src();
1429214323 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1429314324 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 }
1429414357 const target = sema.mod.getTarget();
1429514358 const bit_size = try operand_ty.bitSizeAdvanced(target, sema.kit(block, src));
1429614359 return sema.addIntUnsigned(Type.comptime_int, bit_size);
......@@ -14321,7 +14384,7 @@ fn zirClosureCapture(
1432114384 // value only. In such case we preserve the type and use a dummy runtime value.
1432214385 const operand = try sema.resolveInst(inst_data.operand);
1432314386 const val = (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) orelse
14324 Value.initTag(.generic_poison);
14387 Value.initTag(.unreachable_value);
1432514388
1432614389 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{
1432714390 .ty = try sema.typeOf(operand).copy(sema.perm_arena),
......@@ -14358,7 +14421,35 @@ fn zirClosureGet(
1435814421 scope = scope.parent.?;
1435914422 } 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) {
1436214453 const msg = msg: {
1436314454 const name = name: {
1436414455 const file = sema.owner_decl.getFileScope();
......@@ -17121,7 +17212,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1712117212 try sema.resolveTypeLayout(block, operand_src, operand_ty);
1712217213 const enum_ty = switch (operand_ty.zigTypeTag()) {
1712317214 .EnumLiteral => {
17124 const val = try sema.resolveConstValue(block, .unneeded, operand, undefined);
17215 const val = try sema.resolveConstValue(block, .unneeded, operand, "");
1712517216 const bytes = val.castTag(.enum_literal).?.data;
1712617217 return sema.addStrLit(block, bytes);
1712717218 },
......@@ -18379,7 +18470,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1837918470 return sema.failWithOwnedErrorMsg(msg);
1838018471 }
1838118472
18382 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| {
18473 if (try sema.resolveMaybeUndefVal(block, operand_src, ptr)) |operand_val| {
1838318474 if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) {
1838418475 return sema.failWithUseOfUndef(block, operand_src);
1838518476 }
......@@ -18756,6 +18847,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
1875618847 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
1875718848 } 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
1875918854 switch (ty.containerLayout()) {
1876018855 .Packed => {
1876118856 var bit_sum: u64 = 0;
......@@ -20096,7 +20191,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2009620191 var bound_arg_src: ?LazySrcLoc = null;
2009720192 if (sema.typeOf(func).tag() == .bound_fn) {
2009820193 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, "");
2010020195 const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
2010120196 func = bound_data.func_inst;
2010220197 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
2013920234 break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src);
2014020235 } 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
2014220241 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);
2014320242 const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;
2014420243
......@@ -21197,6 +21296,8 @@ const ExternPosition = enum {
2119721296 ret_ty,
2119821297 param_ty,
2119921298 union_field,
21299 struct_field,
21300 element,
2120021301 other,
2120121302};
2120221303
......@@ -21234,7 +21335,10 @@ fn validateExternType(
2123421335 8, 16, 32, 64, 128 => return true,
2123521336 else => return false,
2123621337 },
21237 .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()),
21338 .Fn => {
21339 if (position != .other) return false;
21340 return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention());
21341 },
2123821342 .Enum => {
2123921343 var buf: Type.Payload.Bits = undefined;
2124021344 return sema.validateExternType(block, src, ty.intTagType(&buf), position);
......@@ -21253,9 +21357,9 @@ fn validateExternType(
2125321357 },
2125421358 .Array => {
2125521359 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);
2125721361 },
21258 .Vector => return sema.validateExternType(block, src, ty.elemType2(), .other),
21362 .Vector => return sema.validateExternType(block, src, ty.elemType2(), .element),
2125921363 .Optional => return ty.isPtrLikeOptional(),
2126021364 }
2126121365}
......@@ -21295,11 +21399,18 @@ fn explainWhyTypeIsNotExtern(
2129521399 } else {
2129621400 try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{});
2129721401 },
21298 .Fn => switch (ty.fnCallingConvention()) {
21299 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),
21300 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),
21301 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),
21302 else => return,
21402 .Fn => {
21403 if (position != .other) {
21404 try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{});
21405 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
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 }
2130321414 },
2130421415 .Enum => {
2130521416 var buf: Type.Payload.Bits = undefined;
......@@ -21315,9 +21426,9 @@ fn explainWhyTypeIsNotExtern(
2131521426 } else if (position == .param_ty) {
2131621427 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
2131721428 }
21318 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position);
21429 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element);
2131921430 },
21320 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position),
21431 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element),
2132121432 .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
2132221433 }
2132321434}
......@@ -22047,7 +22158,7 @@ fn fieldPtr(
2204722158 }
2204822159 },
2204922160 .Type => {
22050 _ = try sema.resolveConstValue(block, .unneeded, object_ptr, undefined);
22161 _ = try sema.resolveConstValue(block, .unneeded, object_ptr, "");
2205122162 const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src);
2205222163 const inner = if (is_pointer_to)
2205322164 try sema.analyzeLoad(block, src, result, object_ptr_src)
......@@ -23375,7 +23486,7 @@ fn coerceExtra(
2337523486
2337623487 // Function body to function pointer.
2337723488 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, "");
2337923490 const fn_decl = fn_val.pointerDecl().?;
2338023491 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
2338123492 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
......@@ -23677,7 +23788,7 @@ fn coerceExtra(
2367723788 },
2367823789 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {
2367923790 .ComptimeFloat => {
23680 const val = try sema.resolveConstValue(block, .unneeded, inst, undefined);
23791 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
2368123792 const result_val = try val.floatCast(sema.arena, dest_ty, target);
2368223793 return try sema.addConstant(dest_ty, result_val);
2368323794 },
......@@ -23735,7 +23846,7 @@ fn coerceExtra(
2373523846 .Enum => switch (inst_ty.zigTypeTag()) {
2373623847 .EnumLiteral => {
2373723848 // enum literal to enum
23738 const val = try sema.resolveConstValue(block, .unneeded, inst, undefined);
23849 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
2373923850 const bytes = val.castTag(.enum_literal).?.data;
2374023851 const field_index = dest_ty.enumFieldIndex(bytes) orelse {
2374123852 const msg = msg: {
......@@ -24805,7 +24916,7 @@ fn coerceVarArgParam(
2480524916 .{},
2480624917 ),
2480724918 .Fn => blk: {
24808 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined);
24919 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
2480924920 const fn_decl = fn_val.pointerDecl().?;
2481024921 break :blk try sema.analyzeDeclRef(fn_decl);
2481124922 },
......@@ -24814,13 +24925,13 @@ fn coerceVarArgParam(
2481424925 };
2481524926
2481624927 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)) {
2481824929 const msg = msg: {
2481924930 const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)});
2482024931 errdefer msg.destroy(sema.gpa);
2482124932
2482224933 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
2482524936 try sema.addDeclaredHereNote(msg, coerced_ty);
2482624937 break :msg msg;
......@@ -26904,10 +27015,14 @@ fn analyzeIsNull(
2690427015 }
2690527016 }
2690627017
27018 const inverted_non_null_res = if (invert_logic) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
2690727019 const operand_ty = sema.typeOf(operand);
2690827020 var buf: Type.Payload.ElemType = undefined;
2690927021 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;
2691127026 }
2691227027 try sema.requireRuntimeBlock(block, src, null);
2691327028 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
2910529220 };
2910629221 return sema.failWithOwnedErrorMsg(msg);
2910729222 }
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)) {
2910929224 const msg = msg: {
2911029225 const tree = try sema.getAstTree(&block_scope);
2911129226 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);
2911229227 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
2911329228 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
2911729232 try sema.addDeclaredHereNote(msg, field.ty);
2911829233 break :msg msg;
src/Zir.zig+11-7
......@@ -402,6 +402,8 @@ pub const Inst = struct {
402402 /// Emits a compile error if an error is ignored.
403403 /// Uses the `un_node` field.
404404 ensure_result_non_error,
405 /// Emits a compile error error union payload is not void.
406 ensure_err_union_payload_void,
405407 /// Create a `E!T` type.
406408 /// Uses the `pl_node` field with `Bin` payload.
407409 error_union_type,
......@@ -646,9 +648,6 @@ pub const Inst = struct {
646648 /// Given a pointer to an error union value, returns the error code. No safety checks.
647649 /// Uses the `un_node` field.
648650 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,
652651 /// An enum literal. Uses the `str_tok` union field.
653652 enum_literal,
654653 /// A switch expression. Uses the `pl_node` union field.
......@@ -1060,6 +1059,7 @@ pub const Inst = struct {
10601059 .elem_val_node,
10611060 .ensure_result_used,
10621061 .ensure_result_non_error,
1062 .ensure_err_union_payload_void,
10631063 .@"export",
10641064 .export_value,
10651065 .field_ptr,
......@@ -1113,7 +1113,6 @@ pub const Inst = struct {
11131113 .err_union_code_ptr,
11141114 .ptr_type,
11151115 .overflow_arithmetic_ptr,
1116 .ensure_err_payload_void,
11171116 .enum_literal,
11181117 .merge_error_sets,
11191118 .error_union_type,
......@@ -1282,7 +1281,7 @@ pub const Inst = struct {
12821281 .dbg_block_end,
12831282 .ensure_result_used,
12841283 .ensure_result_non_error,
1285 .ensure_err_payload_void,
1284 .ensure_err_union_payload_void,
12861285 .set_eval_branch_quota,
12871286 .atomic_store,
12881287 .store,
......@@ -1615,6 +1614,7 @@ pub const Inst = struct {
16151614 .elem_val_node = .pl_node,
16161615 .ensure_result_used = .un_node,
16171616 .ensure_result_non_error = .un_node,
1617 .ensure_err_union_payload_void = .un_node,
16181618 .error_union_type = .pl_node,
16191619 .error_value = .str_tok,
16201620 .@"export" = .pl_node,
......@@ -1677,7 +1677,6 @@ pub const Inst = struct {
16771677 .err_union_payload_unsafe_ptr = .un_node,
16781678 .err_union_code = .un_node,
16791679 .err_union_code_ptr = .un_node,
1680 .ensure_err_payload_void = .un_tok,
16811680 .enum_literal = .str_tok,
16821681 .switch_block = .pl_node,
16831682 .switch_cond = .un_node,
......@@ -3051,11 +3050,16 @@ pub const Inst = struct {
30513050 var multi_i: u32 = 0;
30523051 while (true) : (multi_i += 1) {
30533052 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;
30553056 const body_len = @truncate(u31, zir.extra[extra_index]);
30563057 extra_index += 1;
30573058 const items = zir.refSlice(extra_index, items_len);
30583059 extra_index += items_len;
3060 // Each range has a start and an end.
3061 extra_index += 2 * ranges_len;
3062
30593063 const body = zir.extra[extra_index..][0..body_len];
30603064 extra_index += body_len;
30613065
src/print_zir.zig+1-1
......@@ -162,6 +162,7 @@ const Writer = struct {
162162 .load,
163163 .ensure_result_used,
164164 .ensure_result_non_error,
165 .ensure_err_union_payload_void,
165166 .ret_node,
166167 .ret_load,
167168 .resolve_inferred_alloc,
......@@ -235,7 +236,6 @@ const Writer = struct {
235236
236237 .ref,
237238 .ret_tok,
238 .ensure_err_payload_void,
239239 .closure_capture,
240240 .switch_capture_tag,
241241 => try self.writeUnTok(stream, inst),
src/type.zig+22
......@@ -5664,6 +5664,28 @@ pub const Type = extern union {
56645664 }
56655665 }
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
56675689 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 {
56685690 const struct_obj = ty.castTag(.@"struct").?.data;
56695691 assert(struct_obj.layout == .Packed);
test/behavior.zig+1
......@@ -95,6 +95,7 @@ test {
9595 _ = @import("behavior/bugs/12801-1.zig");
9696 _ = @import("behavior/bugs/12801-2.zig");
9797 _ = @import("behavior/bugs/12885.zig");
98 _ = @import("behavior/bugs/12890.zig");
9899 _ = @import("behavior/bugs/12911.zig");
99100 _ = @import("behavior/bugs/12928.zig");
100101 _ = @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;
77/// A more basic implementation of std.testing.expectError which
88/// does not require formatter/printing support
99fn expectError(expected_err: anyerror, observed_err_union: anytype) !void {
10 if (observed_err_union) {
10 if (observed_err_union) |_| {
1111 return error.TestExpectedError;
1212 } else |err| if (err == expected_err) {
1313 return; // Success
test/behavior/eval.zig+14
......@@ -1398,3 +1398,17 @@ test "continue in inline for inside a comptime switch" {
13981398 }
13991399 try expect(count == 4);
14001400}
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" {
129129 },
130130 }
131131}
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" {
483483 const alignment = @typeInfo(@TypeOf(&S.aligned)).Pointer.alignment;
484484 try std.testing.expect(alignment == 8);
485485}
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" {
310310 try expect(@as(f32, @sizeOf(S)) == 1.0);
311311 }
312312}
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