authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-13 17:35:57+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-09 14:01:01-07:00
logb494f6a9dc078c55aea4b27306178084cccb36a8
tree8e723d7091f143158e0c63a7c9382328e3d6d589
parent7748d2bb44dabbf60bfd7f65b1c5e2ebf0b49207

Merge pull request #13497 from Vexu/stage2-fixes

Stage2 bug fixes

17 files changed, 329 insertions(+), 65 deletions(-)

src/AstGen.zig+156-34
......@@ -339,6 +339,8 @@ pub const ResultInfo = struct {
339339 fn_arg,
340340 /// The expression is the right-hand side of an initializer for a `const` variable
341341 const_init,
342 /// The expression is the right-hand side of an assignment expression.
343 assignment,
342344 /// No specific operator in particular.
343345 none,
344346 };
......@@ -826,7 +828,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
826828
827829 .slice_open => {
828830 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
831
832 maybeAdvanceSourceCursorToMainToken(gz, node);
833 const line = gz.astgen.source_line - gz.decl_line;
834 const column = gz.astgen.source_column;
835
829836 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
837 try emitDbgStmt(gz, line, column);
830838 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{
831839 .lhs = lhs,
832840 .start = start,
......@@ -835,9 +843,15 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
835843 },
836844 .slice => {
837845 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
846
847 maybeAdvanceSourceCursorToMainToken(gz, node);
848 const line = gz.astgen.source_line - gz.decl_line;
849 const column = gz.astgen.source_column;
850
838851 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
839852 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
840853 const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end);
854 try emitDbgStmt(gz, line, column);
841855 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{
842856 .lhs = lhs,
843857 .start = start,
......@@ -847,10 +861,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
847861 },
848862 .slice_sentinel => {
849863 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
864
865 maybeAdvanceSourceCursorToMainToken(gz, node);
866 const line = gz.astgen.source_line - gz.decl_line;
867 const column = gz.astgen.source_column;
868
850869 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
851870 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
852871 const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none;
853872 const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel);
873 try emitDbgStmt(gz, line, column);
854874 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{
855875 .lhs = lhs,
856876 .start = start,
......@@ -881,16 +901,26 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
881901 return rvalue(gz, ri, result, node);
882902 },
883903 .unwrap_optional => switch (ri.rl) {
884 .ref => return gz.addUnNode(
885 .optional_payload_safe_ptr,
886 try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs),
887 node,
888 ),
889 else => return rvalue(gz, ri, try gz.addUnNode(
890 .optional_payload_safe,
891 try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
892 node,
893 ), node),
904 .ref => {
905 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
906
907 maybeAdvanceSourceCursorToMainToken(gz, node);
908 const line = gz.astgen.source_line - gz.decl_line;
909 const column = gz.astgen.source_column;
910 try emitDbgStmt(gz, line, column);
911
912 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);
913 },
914 else => {
915 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
916
917 maybeAdvanceSourceCursorToMainToken(gz, node);
918 const line = gz.astgen.source_line - gz.decl_line;
919 const column = gz.astgen.source_column;
920 try emitDbgStmt(gz, line, column);
921
922 return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node);
923 },
894924 },
895925 .block_two, .block_two_semicolon => {
896926 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
......@@ -3216,7 +3246,7 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
32163246 // This intentionally does not support `@"_"` syntax.
32173247 const ident_name = tree.tokenSlice(main_tokens[lhs]);
32183248 if (mem.eql(u8, ident_name, "_")) {
3219 _ = try expr(gz, scope, .{ .rl = .discard }, rhs);
3249 _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs);
32203250 return;
32213251 }
32223252 }
......@@ -3239,10 +3269,27 @@ fn assignOp(
32393269 const node_datas = tree.nodes.items(.data);
32403270
32413271 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
3272
3273 var line: u32 = undefined;
3274 var column: u32 = undefined;
3275 switch (op_inst_tag) {
3276 .add, .sub, .mul, .div, .mod_rem => {
3277 maybeAdvanceSourceCursorToMainToken(gz, infix_node);
3278 line = gz.astgen.source_line - gz.decl_line;
3279 column = gz.astgen.source_column;
3280 },
3281 else => {},
3282 }
32423283 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
32433284 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);
32443285 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs);
32453286
3287 switch (op_inst_tag) {
3288 .add, .sub, .mul, .div, .mod_rem => {
3289 try emitDbgStmt(gz, line, column);
3290 },
3291 else => {},
3292 }
32463293 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
32473294 .lhs = lhs,
32483295 .rhs = rhs,
......@@ -5294,9 +5341,11 @@ fn orelseCatchExpr(
52945341 // up for this fact by calling rvalue on the else branch.
52955342 const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs);
52965343 const cond = try block_scope.addUnNode(cond_op, operand, node);
5297 const condbr = try block_scope.addCondBr(.condbr, node);
5344 const condbr_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .condbr_inline else .condbr;
5345 const condbr = try block_scope.addCondBr(condbr_tag, node);
52985346
5299 const block = try parent_gz.makeBlockInst(.block, node);
5347 const block_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .block_inline else .block;
5348 const block = try parent_gz.makeBlockInst(block_tag, node);
53005349 try block_scope.setBlockBody(block);
53015350 // block_scope unstacked now, can add new instructions to parent_gz
53025351 try parent_gz.instructions.append(astgen.gpa, block);
......@@ -5471,9 +5520,15 @@ fn addFieldAccess(
54715520 const dot_token = main_tokens[node];
54725521 const field_ident = dot_token + 1;
54735522 const str_index = try astgen.identAsString(field_ident);
5523 const lhs = try expr(gz, scope, lhs_ri, object_node);
5524
5525 maybeAdvanceSourceCursorToMainToken(gz, node);
5526 const line = gz.astgen.source_line - gz.decl_line;
5527 const column = gz.astgen.source_column;
5528 try emitDbgStmt(gz, line, column);
54745529
54755530 return gz.addPlNode(tag, node, Zir.Inst.Field{
5476 .lhs = try expr(gz, scope, lhs_ri, object_node),
5531 .lhs = lhs,
54775532 .field_name_start = str_index,
54785533 });
54795534}
......@@ -5484,18 +5539,33 @@ fn arrayAccess(
54845539 ri: ResultInfo,
54855540 node: Ast.Node.Index,
54865541) InnerError!Zir.Inst.Ref {
5487 const astgen = gz.astgen;
5488 const tree = astgen.tree;
5542 const tree = gz.astgen.tree;
54895543 const node_datas = tree.nodes.items(.data);
54905544 switch (ri.rl) {
5491 .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{
5492 .lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs),
5493 .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs),
5494 }),
5495 else => return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{
5496 .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
5497 .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs),
5498 }), node),
5545 .ref => {
5546 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
5547
5548 maybeAdvanceSourceCursorToMainToken(gz, node);
5549 const line = gz.astgen.source_line - gz.decl_line;
5550 const column = gz.astgen.source_column;
5551
5552 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs);
5553 try emitDbgStmt(gz, line, column);
5554
5555 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
5556 },
5557 else => {
5558 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
5559
5560 maybeAdvanceSourceCursorToMainToken(gz, node);
5561 const line = gz.astgen.source_line - gz.decl_line;
5562 const column = gz.astgen.source_column;
5563
5564 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs);
5565 try emitDbgStmt(gz, line, column);
5566
5567 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
5568 },
54995569 }
55005570}
55015571
......@@ -5510,10 +5580,26 @@ fn simpleBinOp(
55105580 const tree = astgen.tree;
55115581 const node_datas = tree.nodes.items(.data);
55125582
5513 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{
5514 .lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node),
5515 .rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node),
5516 });
5583 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);
5584 var line: u32 = undefined;
5585 var column: u32 = undefined;
5586 switch (op_inst_tag) {
5587 .add, .sub, .mul, .div, .mod_rem => {
5588 maybeAdvanceSourceCursorToMainToken(gz, node);
5589 line = gz.astgen.source_line - gz.decl_line;
5590 column = gz.astgen.source_column;
5591 },
5592 else => {},
5593 }
5594 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);
5595
5596 switch (op_inst_tag) {
5597 .add, .sub, .mul, .div, .mod_rem => {
5598 try emitDbgStmt(gz, line, column);
5599 },
5600 else => {},
5601 }
5602 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
55175603 return rvalue(gz, ri, result, node);
55185604}
55195605
......@@ -5608,9 +5694,11 @@ fn ifExpr(
56085694 }
56095695 };
56105696
5611 const condbr = try block_scope.addCondBr(.condbr, node);
5697 const condbr_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .condbr_inline else .condbr;
5698 const condbr = try block_scope.addCondBr(condbr_tag, node);
56125699
5613 const block = try parent_gz.makeBlockInst(.block, node);
5700 const block_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .block_inline else .block;
5701 const block = try parent_gz.makeBlockInst(block_tag, node);
56145702 try block_scope.setBlockBody(block);
56155703 // block_scope unstacked now, can add new instructions to parent_gz
56165704 try parent_gz.instructions.append(astgen.gpa, block);
......@@ -7084,7 +7172,7 @@ fn localVarRef(
70847172 if (local_val.name == name_str_index) {
70857173 // Locals cannot shadow anything, so we do not need to look for ambiguous
70867174 // references in this case.
7087 if (ri.rl == .discard) {
7175 if (ri.rl == .discard and ri.ctx == .assignment) {
70887176 local_val.discarded = ident_token;
70897177 } else {
70907178 local_val.used = ident_token;
......@@ -7107,7 +7195,7 @@ fn localVarRef(
71077195 .local_ptr => {
71087196 const local_ptr = s.cast(Scope.LocalPtr).?;
71097197 if (local_ptr.name == name_str_index) {
7110 if (ri.rl == .discard) {
7198 if (ri.rl == .discard and ri.ctx == .assignment) {
71117199 local_ptr.discarded = ident_token;
71127200 } else {
71137201 local_ptr.used = ident_token;
......@@ -7969,6 +8057,8 @@ fn builtinCall(
79698057 return rvalue(gz, ri, result, node);
79708058 },
79718059 .err_set_cast => {
8060 try emitDbgNode(gz, node);
8061
79728062 const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{
79738063 .lhs = try typeExpr(gz, scope, params[0]),
79748064 .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),
......@@ -8274,6 +8364,8 @@ fn typeCast(
82748364 rhs_node: Ast.Node.Index,
82758365 tag: Zir.Inst.Tag,
82768366) InnerError!Zir.Inst.Ref {
8367 try emitDbgNode(gz, node);
8368
82778369 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
82788370 .lhs = try typeExpr(gz, scope, lhs_node),
82798371 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
......@@ -8303,6 +8395,10 @@ fn simpleUnOp(
83038395 operand_node: Ast.Node.Index,
83048396 tag: Zir.Inst.Tag,
83058397) InnerError!Zir.Inst.Ref {
8398 switch (tag) {
8399 .tag_name, .error_name, .ptr_to_int => try emitDbgNode(gz, node),
8400 else => {},
8401 }
83068402 const operand = try expr(gz, scope, operand_ri, operand_node);
83078403 const result = try gz.addUnNode(tag, operand, node);
83088404 return rvalue(gz, ri, result, node);
......@@ -8375,6 +8471,8 @@ fn divBuiltin(
83758471 rhs_node: Ast.Node.Index,
83768472 tag: Zir.Inst.Tag,
83778473) InnerError!Zir.Inst.Ref {
8474 try emitDbgNode(gz, node);
8475
83788476 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
83798477 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),
83808478 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
......@@ -8428,8 +8526,15 @@ fn shiftOp(
84288526 tag: Zir.Inst.Tag,
84298527) InnerError!Zir.Inst.Ref {
84308528 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
8529
8530 maybeAdvanceSourceCursorToMainToken(gz, node);
8531 const line = gz.astgen.source_line - gz.decl_line;
8532 const column = gz.astgen.source_column;
8533
84318534 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
84328535 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
8536
8537 try emitDbgStmt(gz, line, column);
84338538 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
84348539 .lhs = lhs,
84358540 .rhs = rhs,
......@@ -10668,14 +10773,19 @@ const GenZir = struct {
1066810773 gz.break_result_info = parent_ri;
1066910774 },
1067010775
10671 .discard, .none, .ref => {
10776 .none, .ref => {
1067210777 gz.rl_ty_inst = .none;
1067310778 gz.break_result_info = parent_ri;
1067410779 },
1067510780
10781 .discard => {
10782 gz.rl_ty_inst = .none;
10783 gz.break_result_info = .{ .rl = .discard };
10784 },
10785
1067610786 .ptr => |ptr_res| {
1067710787 gz.rl_ty_inst = .none;
10678 gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } } };
10788 gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } }, .ctx = parent_ri.ctx };
1067910789 },
1068010790
1068110791 .inferred_ptr => |ptr| {
......@@ -12054,6 +12164,18 @@ fn detectLocalShadowing(
1205412164 };
1205512165}
1205612166
12167/// Advances the source cursor to the main token of `node` if not in comptime scope.
12168/// Usually paired with `emitDbgStmt`.
12169fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) void {
12170 if (gz.force_comptime) return;
12171
12172 const tree = gz.astgen.tree;
12173 const token_starts = tree.tokens.items(.start);
12174 const main_tokens = tree.nodes.items(.main_token);
12175 const node_start = token_starts[main_tokens[node]];
12176 gz.astgen.advanceSourceCursor(node_start);
12177}
12178
1205712179/// Advances the source cursor to the beginning of `node`.
1205812180fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {
1205912181 const tree = astgen.tree;
src/Autodoc.zig+12-3
......@@ -2129,7 +2129,15 @@ fn walkInstruction(
21292129 file,
21302130 parent_scope,
21312131 parent_src,
2132 getBlockInlineBreak(file.zir, inst_index),
2132 getBlockInlineBreak(file.zir, inst_index) orelse {
2133 const res = DocData.WalkResult{ .expr = .{
2134 .comptimeExpr = self.comptime_exprs.items.len,
2135 } };
2136 try self.comptime_exprs.append(self.arena, .{
2137 .code = "if (...) { ... }",
2138 });
2139 return res;
2140 },
21332141 need_type,
21342142 );
21352143 },
......@@ -3155,7 +3163,7 @@ fn walkDecls(
31553163 2 => {
31563164 // decl test
31573165 const decl_being_tested = scope.resolveDeclName(doc_comment_index);
3158 const func_index = getBlockInlineBreak(file.zir, value_index);
3166 const func_index = getBlockInlineBreak(file.zir, value_index).?;
31593167
31603168 const pl_node = data[Zir.refToIndex(func_index).?].pl_node;
31613169 const fn_src = try self.srcLocInfo(file, pl_node.src_node, decl_src);
......@@ -4301,12 +4309,13 @@ fn walkRef(
43014309 }
43024310}
43034311
4304fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref {
4312fn getBlockInlineBreak(zir: Zir, inst_index: usize) ?Zir.Inst.Ref {
43054313 const tags = zir.instructions.items(.tag);
43064314 const data = zir.instructions.items(.data);
43074315 const pl_node = data[inst_index].pl_node;
43084316 const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index);
43094317 const break_index = zir.extra[extra.end..][extra.data.body_len - 1];
4318 if (tags[break_index] == .condbr_inline) return null;
43104319 std.debug.assert(tags[break_index] == .break_inline);
43114320 return data[break_index].@"break".operand;
43124321}
src/Sema.zig+9-12
......@@ -1491,6 +1491,8 @@ fn analyzeBodyInner(
14911491 return err;
14921492 };
14931493 const inline_body = if (cond.val.toBool()) then_body else else_body;
1494
1495 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
14941496 const old_runtime_index = block.runtime_index;
14951497 defer block.runtime_index = old_runtime_index;
14961498 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
......@@ -5658,14 +5660,14 @@ fn lookupInNamespace(
56585660 const src_file = block.namespace.file_scope;
56595661
56605662 const gpa = sema.gpa;
5661 var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{};
5663 var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{};
56625664 defer checked_namespaces.deinit(gpa);
56635665
56645666 // Keep track of name conflicts for error notes.
56655667 var candidates: std.ArrayListUnmanaged(Decl.Index) = .{};
56665668 defer candidates.deinit(gpa);
56675669
5668 try checked_namespaces.put(gpa, namespace, {});
5670 try checked_namespaces.put(gpa, namespace, namespace.file_scope == src_file);
56695671 var check_i: usize = 0;
56705672
56715673 while (check_i < checked_namespaces.count()) : (check_i += 1) {
......@@ -5674,7 +5676,7 @@ fn lookupInNamespace(
56745676 // Skip decls which are not marked pub, which are in a different
56755677 // file than the `a.b`/`@hasDecl` syntax.
56765678 const decl = mod.declPtr(decl_index);
5677 if (decl.is_pub or src_file == decl.getFileScope()) {
5679 if (decl.is_pub or (src_file == decl.getFileScope() and checked_namespaces.values()[check_i])) {
56785680 try candidates.append(gpa, decl_index);
56795681 }
56805682 }
......@@ -5693,7 +5695,7 @@ fn lookupInNamespace(
56935695 try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index);
56945696 const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data;
56955697 const sub_ns = ns_ty.getNamespace().?;
5696 try checked_namespaces.put(gpa, sub_ns, {});
5698 try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScope());
56975699 }
56985700 }
56995701
......@@ -6331,6 +6333,7 @@ fn analyzeCall(
63316333 .instructions = .{},
63326334 .label = null,
63336335 .inlining = &inlining,
6336 .is_typeof = block.is_typeof,
63346337 .is_comptime = is_comptime_call,
63356338 .comptime_reason = comptime_reason,
63366339 .error_return_trace_index = block.error_return_trace_index,
......@@ -16530,9 +16533,6 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1653016533 // This is only relevant at runtime.
1653116534 if (block.is_comptime or block.is_typeof) return;
1653216535
16533 // This is only relevant within functions.
16534 if (sema.func == null) return;
16535
1653616536 const save_index = inst_data.operand == .none or b: {
1653716537 const operand = try sema.resolveInst(inst_data.operand);
1653816538 const operand_ty = sema.typeOf(operand);
......@@ -20179,8 +20179,8 @@ fn analyzeShuffle(
2017920179 .elem_type = elem_ty,
2018020180 });
2018120181
20182 if (maybe_a_len == null) a = try sema.addConstUndef(a_ty);
20183 if (maybe_b_len == null) b = try sema.addConstUndef(b_ty);
20182 if (maybe_a_len == null) a = try sema.addConstUndef(a_ty) else a = try sema.coerce(block, a_ty, a, a_src);
20183 if (maybe_b_len == null) b = try sema.addConstUndef(b_ty) else b = try sema.coerce(block, b_ty, b, b_src);
2018420184
2018520185 const operand_info = [2]std.meta.Tuple(&.{ u64, LazySrcLoc, Type }){
2018620186 .{ a_len, a_src, a_ty },
......@@ -27503,9 +27503,6 @@ fn analyzeLoad(
2750327503 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
2750427504 return sema.addConstant(elem_ty, elem_val);
2750527505 }
27506 if (block.is_typeof) {
27507 return sema.addConstUndef(elem_ty);
27508 }
2750927506 }
2751027507
2751127508 return block.addTyOp(.load, elem_ty, ptr);
src/codegen/llvm.zig+17-14
......@@ -1966,7 +1966,7 @@ pub const Object = struct {
19661966
19671967 for (tuple.types) |field_ty, i| {
19681968 const field_val = tuple.values[i];
1969 if (field_val.tag() != .unreachable_value) continue;
1969 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
19701970
19711971 const field_size = field_ty.abiSize(target);
19721972 const field_align = field_ty.abiAlignment(target);
......@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {
29012901
29022902 for (tuple.types) |field_ty, i| {
29032903 const field_val = tuple.values[i];
2904 if (field_val.tag() != .unreachable_value) continue;
2904 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
29052905
29062906 const field_align = field_ty.abiAlignment(target);
29072907 big_align = @max(big_align, field_align);
......@@ -3198,7 +3198,8 @@ pub const DeclGen = struct {
31983198 /// There are other similar cases handled here as well.
31993199 fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type {
32003200 const lower_elem_ty = switch (elem_ty.zigTypeTag()) {
3201 .Opaque, .Fn => true,
3201 .Opaque => true,
3202 .Fn => !elem_ty.fnInfo().is_generic,
32023203 .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(),
32033204 else => elem_ty.hasRuntimeBitsIgnoreComptime(),
32043205 };
......@@ -4145,7 +4146,9 @@ pub const DeclGen = struct {
41454146 }
41464147
41474148 const is_fn_body = decl.ty.zigTypeTag() == .Fn;
4148 if (!is_fn_body and !decl.ty.hasRuntimeBits()) {
4149 if ((!is_fn_body and !decl.ty.hasRuntimeBits()) or
4150 (is_fn_body and decl.ty.fnInfo().is_generic))
4151 {
41494152 return self.lowerPtrToVoid(tv.ty);
41504153 }
41514154
......@@ -8671,9 +8674,9 @@ pub const FuncGen = struct {
86718674 const arena = arena_allocator.allocator();
86728675
86738676 const mod = self.dg.module;
8674 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{
8675 try mod.declPtr(enum_decl).getFullyQualifiedName(mod),
8676 });
8677 const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);
8678 defer self.gpa.free(fqn);
8679 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn});
86778680
86788681 var int_tag_type_buffer: Type.Payload.Bits = undefined;
86798682 const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer);
......@@ -8752,9 +8755,9 @@ pub const FuncGen = struct {
87528755 const arena = arena_allocator.allocator();
87538756
87548757 const mod = self.dg.module;
8755 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{
8756 try mod.declPtr(enum_decl).getFullyQualifiedName(mod),
8757 });
8758 const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);
8759 defer self.gpa.free(fqn);
8760 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
87588761
87598762 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
87608763 const llvm_ret_ty = try self.dg.lowerType(slice_ty);
......@@ -10204,7 +10207,7 @@ fn llvmFieldIndex(
1020410207 const tuple = ty.tupleFields();
1020510208 var llvm_field_index: c_uint = 0;
1020610209 for (tuple.types) |field_ty, i| {
10207 if (tuple.values[i].tag() != .unreachable_value) continue;
10210 if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
1020810211
1020910212 const field_align = field_ty.abiAlignment(target);
1021010213 big_align = @max(big_align, field_align);
......@@ -10216,7 +10219,7 @@ fn llvmFieldIndex(
1021610219 llvm_field_index += 1;
1021710220 }
1021810221
10219 if (field_index == i) {
10222 if (field_index <= i) {
1022010223 ptr_pl_buf.* = .{
1022110224 .data = .{
1022210225 .pointee_type = field_ty,
......@@ -10249,7 +10252,7 @@ fn llvmFieldIndex(
1024910252 llvm_field_index += 1;
1025010253 }
1025110254
10252 if (field_index == i) {
10255 if (field_index <= i) {
1025310256 ptr_pl_buf.* = .{
1025410257 .data = .{
1025510258 .pointee_type = field.ty,
......@@ -10768,7 +10771,7 @@ fn isByRef(ty: Type) bool {
1076810771 const tuple = ty.tupleFields();
1076910772 var count: usize = 0;
1077010773 for (tuple.values) |field_val, i| {
10771 if (field_val.tag() != .unreachable_value) continue;
10774 if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits()) continue;
1077210775
1077310776 count += 1;
1077410777 if (count > max_fields_byval) return true;
src/type.zig+4-2
......@@ -640,7 +640,9 @@ pub const Type = extern union {
640640 const a_info = a.fnInfo();
641641 const b_info = b.fnInfo();
642642
643 if (!eql(a_info.return_type, b_info.return_type, mod))
643 if (a_info.return_type.tag() != .generic_poison and
644 b_info.return_type.tag() != .generic_poison and
645 !eql(a_info.return_type, b_info.return_type, mod))
644646 return false;
645647
646648 if (a_info.is_var_args != b_info.is_var_args)
......@@ -5757,7 +5759,7 @@ pub const Type = extern union {
57575759
57585760 for (tuple.types) |field_ty, i| {
57595761 const field_val = tuple.values[i];
5760 if (field_val.tag() != .unreachable_value) {
5762 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) {
57615763 // comptime field
57625764 if (i == index) return offset;
57635765 continue;
test/behavior/eval.zig+8
......@@ -1499,3 +1499,11 @@ test "non-optional and optional array elements concatenated" {
14991499 var index: usize = 0;
15001500 try expect(array[index].? == 'A');
15011501}
1502
1503test "inline call in @TypeOf inherits is_inline property" {
1504 const S = struct {
1505 inline fn doNothing() void {}
1506 const T = @TypeOf(doNothing());
1507 };
1508 try expect(S.T == void);
1509}
test/behavior/generics.zig+12
......@@ -405,3 +405,15 @@ test "null sentinel pointer passed as generic argument" {
405405 };
406406 try S.doTheTest((@intToPtr([*:null]const [*c]const u8, 8)));
407407}
408
409test "generic function passed as comptime argument" {
410 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
411
412 const S = struct {
413 fn doMath(comptime f: fn (type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void {
414 const result = try f(i32, a, b);
415 try expect(result == 11);
416 }
417 };
418 try S.doMath(std.math.add, 5, 6);
419}
test/behavior/pointers.zig+17
......@@ -489,3 +489,20 @@ test "ptrCast comptime known slice to C pointer" {
489489 var p = @ptrCast([*c]const u8, s);
490490 try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0));
491491}
492
493test "ptrToInt on a generic function" {
494 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
496 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO
497 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO
498
499 const S = struct {
500 fn generic(i: anytype) @TypeOf(i) {
501 return i;
502 }
503 fn doTheTest(a: anytype) !void {
504 try expect(@ptrToInt(a) != 0);
505 }
506 };
507 try S.doTheTest(&S.generic);
508}
test/behavior/struct.zig+20
......@@ -1398,3 +1398,23 @@ test "under-aligned struct field" {
13981398 const result = std.mem.readIntNative(u64, array[4..12]);
13991399 try expect(result == 1234);
14001400}
1401
1402test "address of zero-bit field is equal to address of only field" {
1403 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1405 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1406 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1407
1408 {
1409 const A = struct { b: void = {}, u: u8 };
1410 var a = A{ .u = 0 };
1411 const a_ptr = @fieldParentPtr(A, "b", &a.b);
1412 try std.testing.expectEqual(&a, a_ptr);
1413 }
1414 {
1415 const A = struct { u: u8, b: void = {} };
1416 var a = A{ .u = 0 };
1417 const a_ptr = @fieldParentPtr(A, "b", &a.b);
1418 try std.testing.expectEqual(&a, a_ptr);
1419 }
1420}
test/behavior/tuple.zig+10
......@@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" {
323323 var s: State = undefined;
324324 try expect(s.do() == 0);
325325}
326
327test "tuple type with void field and a runtime field" {
328 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
329 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
330 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
331
332 const T = std.meta.Tuple(&[_]type{ usize, void });
333 var t: T = .{ 5, {} };
334 try expect(t[0] == 5);
335}
test/behavior/usingnamespace.zig+4
......@@ -75,3 +75,7 @@ test {
7575 const a = AA.b(42);
7676 try expect(a.x == AA.c().expected);
7777}
78
79comptime {
80 _ = @import("usingnamespace/file_1.zig");
81}
test/behavior/usingnamespace/file_0.zig created+1
......@@ -0,0 +1 @@
1pub const A = 123;
test/behavior/usingnamespace/file_1.zig created+9
......@@ -0,0 +1,9 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const imports = @import("imports.zig");
4
5const A = 456;
6
7test {
8 try expect(imports.A == 123);
9}
test/behavior/usingnamespace/imports.zig created+5
......@@ -0,0 +1,5 @@
1const file_0 = @import("file_0.zig");
2const file_1 = @import("file_1.zig");
3
4pub usingnamespace file_0;
5pub usingnamespace file_1;
test/behavior/vector.zig+15
......@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33const mem = std.mem;
44const math = std.math;
55const expect = std.testing.expect;
6const expectEqual = std.testing.expectEqual;
67
78test "implicit cast vector to array - bool" {
89 if (builtin.zig_backend == .stage1) {
......@@ -1231,3 +1232,17 @@ test "modRem with zero divisor" {
12311232 _ = zeros[0];
12321233 }
12331234}
1235
1236test "array operands to shuffle are coerced to vectors" {
1237 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1238 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1239 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1242
1243 const mask = [5]i32{ -1, 0, 1, 2, 3 };
1244
1245 var a = [5]u32{ 3, 5, 7, 9, 0 };
1246 var b = @shuffle(u32, a, @splat(5, @as(u24, 0)), mask);
1247 try expectEqual([_]u32{ 0, 3, 5, 7, 9 }, b);
1248}
test/cases/compile_errors/branch_in_comptime_only_scope_uses_condbr_inline.zig created+22
......@@ -0,0 +1,22 @@
1pub export fn entry1() void {
2 var x: u32 = 3;
3 _ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{
4 if (x > 1) 1 else -1,
5 });
6}
7
8pub export fn entry2() void {
9 var y: ?i8 = -1;
10 _ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{
11 y orelse 1,
12 });
13}
14
15// error
16// backend=stage2
17// target=native
18//
19// :4:15: error: unable to resolve comptime value
20// :4:15: note: condition in comptime branch must be comptime-known
21// :11:11: error: unable to resolve comptime value
22// :11:11: note: condition in comptime branch must be comptime-known
test/cases/compile_errors/pointless discard.zig +8
......@@ -3,6 +3,14 @@ export fn foo() void {
33 x += 1;
44 _ = x;
55}
6export fn bar() void {
7 var b: u32 = 1;
8 _ = blk: {
9 const a = 1;
10 b = a;
11 break :blk a;
12 };
13}
614
715// error
816// backend=stage2