| author | |
| committer | |
| log | 99616216c3e841554240d6f10b75d574cc2d05dd |
| tree | 4db7fa671940732149e8a088378154874e1ac3d3 |
| parent | 8a5818535b83ba87849cb09de9f1ccd32e8bb480 |
| parent | 87cf2783ebdf96e3dfa1c24a53dba301591d5f07 |
| signature |
Stage2 bug fixes17 files changed, 329 insertions(+), 65 deletions(-)
src/AstGen.zig+156-34| ... | ... | @@ -339,6 +339,8 @@ pub const ResultInfo = struct { |
| 339 | 339 | fn_arg, |
| 340 | 340 | /// The expression is the right-hand side of an initializer for a `const` variable |
| 341 | 341 | const_init, |
| 342 | /// The expression is the right-hand side of an assignment expression. | |
| 343 | assignment, | |
| 342 | 344 | /// No specific operator in particular. |
| 343 | 345 | none, |
| 344 | 346 | }; |
| ... | ... | @@ -826,7 +828,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 826 | 828 | |
| 827 | 829 | .slice_open => { |
| 828 | 830 | 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 | ||
| 829 | 836 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); |
| 837 | try emitDbgStmt(gz, line, column); | |
| 830 | 838 | const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{ |
| 831 | 839 | .lhs = lhs, |
| 832 | 840 | .start = start, |
| ... | ... | @@ -835,9 +843,15 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 835 | 843 | }, |
| 836 | 844 | .slice => { |
| 837 | 845 | 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 | ||
| 838 | 851 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice); |
| 839 | 852 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start); |
| 840 | 853 | const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end); |
| 854 | try emitDbgStmt(gz, line, column); | |
| 841 | 855 | const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{ |
| 842 | 856 | .lhs = lhs, |
| 843 | 857 | .start = start, |
| ... | ... | @@ -847,10 +861,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 847 | 861 | }, |
| 848 | 862 | .slice_sentinel => { |
| 849 | 863 | 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 | ||
| 850 | 869 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel); |
| 851 | 870 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start); |
| 852 | 871 | const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none; |
| 853 | 872 | const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel); |
| 873 | try emitDbgStmt(gz, line, column); | |
| 854 | 874 | const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{ |
| 855 | 875 | .lhs = lhs, |
| 856 | 876 | .start = start, |
| ... | ... | @@ -881,16 +901,26 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 881 | 901 | return rvalue(gz, ri, result, node); |
| 882 | 902 | }, |
| 883 | 903 | .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 | }, | |
| 894 | 924 | }, |
| 895 | 925 | .block_two, .block_two_semicolon => { |
| 896 | 926 | 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 |
| 3216 | 3246 | // This intentionally does not support `@"_"` syntax. |
| 3217 | 3247 | const ident_name = tree.tokenSlice(main_tokens[lhs]); |
| 3218 | 3248 | if (mem.eql(u8, ident_name, "_")) { |
| 3219 | _ = try expr(gz, scope, .{ .rl = .discard }, rhs); | |
| 3249 | _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs); | |
| 3220 | 3250 | return; |
| 3221 | 3251 | } |
| 3222 | 3252 | } |
| ... | ... | @@ -3239,10 +3269,27 @@ fn assignOp( |
| 3239 | 3269 | const node_datas = tree.nodes.items(.data); |
| 3240 | 3270 | |
| 3241 | 3271 | 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 | } | |
| 3242 | 3283 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3243 | 3284 | const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node); |
| 3244 | 3285 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs); |
| 3245 | 3286 | |
| 3287 | switch (op_inst_tag) { | |
| 3288 | .add, .sub, .mul, .div, .mod_rem => { | |
| 3289 | try emitDbgStmt(gz, line, column); | |
| 3290 | }, | |
| 3291 | else => {}, | |
| 3292 | } | |
| 3246 | 3293 | const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ |
| 3247 | 3294 | .lhs = lhs, |
| 3248 | 3295 | .rhs = rhs, |
| ... | ... | @@ -5294,9 +5341,11 @@ fn orelseCatchExpr( |
| 5294 | 5341 | // up for this fact by calling rvalue on the else branch. |
| 5295 | 5342 | const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs); |
| 5296 | 5343 | 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); | |
| 5298 | 5346 | |
| 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); | |
| 5300 | 5349 | try block_scope.setBlockBody(block); |
| 5301 | 5350 | // block_scope unstacked now, can add new instructions to parent_gz |
| 5302 | 5351 | try parent_gz.instructions.append(astgen.gpa, block); |
| ... | ... | @@ -5471,9 +5520,15 @@ fn addFieldAccess( |
| 5471 | 5520 | const dot_token = main_tokens[node]; |
| 5472 | 5521 | const field_ident = dot_token + 1; |
| 5473 | 5522 | 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); | |
| 5474 | 5529 | |
| 5475 | 5530 | return gz.addPlNode(tag, node, Zir.Inst.Field{ |
| 5476 | .lhs = try expr(gz, scope, lhs_ri, object_node), | |
| 5531 | .lhs = lhs, | |
| 5477 | 5532 | .field_name_start = str_index, |
| 5478 | 5533 | }); |
| 5479 | 5534 | } |
| ... | ... | @@ -5484,18 +5539,33 @@ fn arrayAccess( |
| 5484 | 5539 | ri: ResultInfo, |
| 5485 | 5540 | node: Ast.Node.Index, |
| 5486 | 5541 | ) InnerError!Zir.Inst.Ref { |
| 5487 | const astgen = gz.astgen; | |
| 5488 | const tree = astgen.tree; | |
| 5542 | const tree = gz.astgen.tree; | |
| 5489 | 5543 | const node_datas = tree.nodes.items(.data); |
| 5490 | 5544 | 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 | }, | |
| 5499 | 5569 | } |
| 5500 | 5570 | } |
| 5501 | 5571 | |
| ... | ... | @@ -5510,10 +5580,26 @@ fn simpleBinOp( |
| 5510 | 5580 | const tree = astgen.tree; |
| 5511 | 5581 | const node_datas = tree.nodes.items(.data); |
| 5512 | 5582 | |
| 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 }); | |
| 5517 | 5603 | return rvalue(gz, ri, result, node); |
| 5518 | 5604 | } |
| 5519 | 5605 | |
| ... | ... | @@ -5608,9 +5694,11 @@ fn ifExpr( |
| 5608 | 5694 | } |
| 5609 | 5695 | }; |
| 5610 | 5696 | |
| 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); | |
| 5612 | 5699 | |
| 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); | |
| 5614 | 5702 | try block_scope.setBlockBody(block); |
| 5615 | 5703 | // block_scope unstacked now, can add new instructions to parent_gz |
| 5616 | 5704 | try parent_gz.instructions.append(astgen.gpa, block); |
| ... | ... | @@ -7084,7 +7172,7 @@ fn localVarRef( |
| 7084 | 7172 | if (local_val.name == name_str_index) { |
| 7085 | 7173 | // Locals cannot shadow anything, so we do not need to look for ambiguous |
| 7086 | 7174 | // references in this case. |
| 7087 | if (ri.rl == .discard) { | |
| 7175 | if (ri.rl == .discard and ri.ctx == .assignment) { | |
| 7088 | 7176 | local_val.discarded = ident_token; |
| 7089 | 7177 | } else { |
| 7090 | 7178 | local_val.used = ident_token; |
| ... | ... | @@ -7107,7 +7195,7 @@ fn localVarRef( |
| 7107 | 7195 | .local_ptr => { |
| 7108 | 7196 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 7109 | 7197 | if (local_ptr.name == name_str_index) { |
| 7110 | if (ri.rl == .discard) { | |
| 7198 | if (ri.rl == .discard and ri.ctx == .assignment) { | |
| 7111 | 7199 | local_ptr.discarded = ident_token; |
| 7112 | 7200 | } else { |
| 7113 | 7201 | local_ptr.used = ident_token; |
| ... | ... | @@ -7969,6 +8057,8 @@ fn builtinCall( |
| 7969 | 8057 | return rvalue(gz, ri, result, node); |
| 7970 | 8058 | }, |
| 7971 | 8059 | .err_set_cast => { |
| 8060 | try emitDbgNode(gz, node); | |
| 8061 | ||
| 7972 | 8062 | const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{ |
| 7973 | 8063 | .lhs = try typeExpr(gz, scope, params[0]), |
| 7974 | 8064 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| ... | ... | @@ -8274,6 +8364,8 @@ fn typeCast( |
| 8274 | 8364 | rhs_node: Ast.Node.Index, |
| 8275 | 8365 | tag: Zir.Inst.Tag, |
| 8276 | 8366 | ) InnerError!Zir.Inst.Ref { |
| 8367 | try emitDbgNode(gz, node); | |
| 8368 | ||
| 8277 | 8369 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8278 | 8370 | .lhs = try typeExpr(gz, scope, lhs_node), |
| 8279 | 8371 | .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), |
| ... | ... | @@ -8303,6 +8395,10 @@ fn simpleUnOp( |
| 8303 | 8395 | operand_node: Ast.Node.Index, |
| 8304 | 8396 | tag: Zir.Inst.Tag, |
| 8305 | 8397 | ) InnerError!Zir.Inst.Ref { |
| 8398 | switch (tag) { | |
| 8399 | .tag_name, .error_name, .ptr_to_int => try emitDbgNode(gz, node), | |
| 8400 | else => {}, | |
| 8401 | } | |
| 8306 | 8402 | const operand = try expr(gz, scope, operand_ri, operand_node); |
| 8307 | 8403 | const result = try gz.addUnNode(tag, operand, node); |
| 8308 | 8404 | return rvalue(gz, ri, result, node); |
| ... | ... | @@ -8375,6 +8471,8 @@ fn divBuiltin( |
| 8375 | 8471 | rhs_node: Ast.Node.Index, |
| 8376 | 8472 | tag: Zir.Inst.Tag, |
| 8377 | 8473 | ) InnerError!Zir.Inst.Ref { |
| 8474 | try emitDbgNode(gz, node); | |
| 8475 | ||
| 8378 | 8476 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8379 | 8477 | .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node), |
| 8380 | 8478 | .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), |
| ... | ... | @@ -8428,8 +8526,15 @@ fn shiftOp( |
| 8428 | 8526 | tag: Zir.Inst.Tag, |
| 8429 | 8527 | ) InnerError!Zir.Inst.Ref { |
| 8430 | 8528 | 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 | ||
| 8431 | 8534 | const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node); |
| 8432 | 8535 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node); |
| 8536 | ||
| 8537 | try emitDbgStmt(gz, line, column); | |
| 8433 | 8538 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8434 | 8539 | .lhs = lhs, |
| 8435 | 8540 | .rhs = rhs, |
| ... | ... | @@ -10668,14 +10773,19 @@ const GenZir = struct { |
| 10668 | 10773 | gz.break_result_info = parent_ri; |
| 10669 | 10774 | }, |
| 10670 | 10775 | |
| 10671 | .discard, .none, .ref => { | |
| 10776 | .none, .ref => { | |
| 10672 | 10777 | gz.rl_ty_inst = .none; |
| 10673 | 10778 | gz.break_result_info = parent_ri; |
| 10674 | 10779 | }, |
| 10675 | 10780 | |
| 10781 | .discard => { | |
| 10782 | gz.rl_ty_inst = .none; | |
| 10783 | gz.break_result_info = .{ .rl = .discard }; | |
| 10784 | }, | |
| 10785 | ||
| 10676 | 10786 | .ptr => |ptr_res| { |
| 10677 | 10787 | 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 }; | |
| 10679 | 10789 | }, |
| 10680 | 10790 | |
| 10681 | 10791 | .inferred_ptr => |ptr| { |
| ... | ... | @@ -12054,6 +12164,18 @@ fn detectLocalShadowing( |
| 12054 | 12164 | }; |
| 12055 | 12165 | } |
| 12056 | 12166 | |
| 12167 | /// Advances the source cursor to the main token of `node` if not in comptime scope. | |
| 12168 | /// Usually paired with `emitDbgStmt`. | |
| 12169 | fn 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 | ||
| 12057 | 12179 | /// Advances the source cursor to the beginning of `node`. |
| 12058 | 12180 | fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void { |
| 12059 | 12181 | const tree = astgen.tree; |
src/Autodoc.zig+12-3| ... | ... | @@ -2129,7 +2129,15 @@ fn walkInstruction( |
| 2129 | 2129 | file, |
| 2130 | 2130 | parent_scope, |
| 2131 | 2131 | 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 | }, | |
| 2133 | 2141 | need_type, |
| 2134 | 2142 | ); |
| 2135 | 2143 | }, |
| ... | ... | @@ -3155,7 +3163,7 @@ fn walkDecls( |
| 3155 | 3163 | 2 => { |
| 3156 | 3164 | // decl test |
| 3157 | 3165 | 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).?; | |
| 3159 | 3167 | |
| 3160 | 3168 | const pl_node = data[Zir.refToIndex(func_index).?].pl_node; |
| 3161 | 3169 | const fn_src = try self.srcLocInfo(file, pl_node.src_node, decl_src); |
| ... | ... | @@ -4301,12 +4309,13 @@ fn walkRef( |
| 4301 | 4309 | } |
| 4302 | 4310 | } |
| 4303 | 4311 | |
| 4304 | fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { | |
| 4312 | fn getBlockInlineBreak(zir: Zir, inst_index: usize) ?Zir.Inst.Ref { | |
| 4305 | 4313 | const tags = zir.instructions.items(.tag); |
| 4306 | 4314 | const data = zir.instructions.items(.data); |
| 4307 | 4315 | const pl_node = data[inst_index].pl_node; |
| 4308 | 4316 | const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index); |
| 4309 | 4317 | const break_index = zir.extra[extra.end..][extra.data.body_len - 1]; |
| 4318 | if (tags[break_index] == .condbr_inline) return null; | |
| 4310 | 4319 | std.debug.assert(tags[break_index] == .break_inline); |
| 4311 | 4320 | return data[break_index].@"break".operand; |
| 4312 | 4321 | } |
src/Sema.zig+9-12| ... | ... | @@ -1491,6 +1491,8 @@ fn analyzeBodyInner( |
| 1491 | 1491 | return err; |
| 1492 | 1492 | }; |
| 1493 | 1493 | 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); | |
| 1494 | 1496 | const old_runtime_index = block.runtime_index; |
| 1495 | 1497 | defer block.runtime_index = old_runtime_index; |
| 1496 | 1498 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| ... | ... | @@ -5658,14 +5660,14 @@ fn lookupInNamespace( |
| 5658 | 5660 | const src_file = block.namespace.file_scope; |
| 5659 | 5661 | |
| 5660 | 5662 | const gpa = sema.gpa; |
| 5661 | var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{}; | |
| 5663 | var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{}; | |
| 5662 | 5664 | defer checked_namespaces.deinit(gpa); |
| 5663 | 5665 | |
| 5664 | 5666 | // Keep track of name conflicts for error notes. |
| 5665 | 5667 | var candidates: std.ArrayListUnmanaged(Decl.Index) = .{}; |
| 5666 | 5668 | defer candidates.deinit(gpa); |
| 5667 | 5669 | |
| 5668 | try checked_namespaces.put(gpa, namespace, {}); | |
| 5670 | try checked_namespaces.put(gpa, namespace, namespace.file_scope == src_file); | |
| 5669 | 5671 | var check_i: usize = 0; |
| 5670 | 5672 | |
| 5671 | 5673 | while (check_i < checked_namespaces.count()) : (check_i += 1) { |
| ... | ... | @@ -5674,7 +5676,7 @@ fn lookupInNamespace( |
| 5674 | 5676 | // Skip decls which are not marked pub, which are in a different |
| 5675 | 5677 | // file than the `a.b`/`@hasDecl` syntax. |
| 5676 | 5678 | 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])) { | |
| 5678 | 5680 | try candidates.append(gpa, decl_index); |
| 5679 | 5681 | } |
| 5680 | 5682 | } |
| ... | ... | @@ -5693,7 +5695,7 @@ fn lookupInNamespace( |
| 5693 | 5695 | try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index); |
| 5694 | 5696 | const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data; |
| 5695 | 5697 | 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()); | |
| 5697 | 5699 | } |
| 5698 | 5700 | } |
| 5699 | 5701 | |
| ... | ... | @@ -6331,6 +6333,7 @@ fn analyzeCall( |
| 6331 | 6333 | .instructions = .{}, |
| 6332 | 6334 | .label = null, |
| 6333 | 6335 | .inlining = &inlining, |
| 6336 | .is_typeof = block.is_typeof, | |
| 6334 | 6337 | .is_comptime = is_comptime_call, |
| 6335 | 6338 | .comptime_reason = comptime_reason, |
| 6336 | 6339 | .error_return_trace_index = block.error_return_trace_index, |
| ... | ... | @@ -16530,9 +16533,6 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 16530 | 16533 | // This is only relevant at runtime. |
| 16531 | 16534 | if (block.is_comptime or block.is_typeof) return; |
| 16532 | 16535 | |
| 16533 | // This is only relevant within functions. | |
| 16534 | if (sema.func == null) return; | |
| 16535 | ||
| 16536 | 16536 | const save_index = inst_data.operand == .none or b: { |
| 16537 | 16537 | const operand = try sema.resolveInst(inst_data.operand); |
| 16538 | 16538 | const operand_ty = sema.typeOf(operand); |
| ... | ... | @@ -20179,8 +20179,8 @@ fn analyzeShuffle( |
| 20179 | 20179 | .elem_type = elem_ty, |
| 20180 | 20180 | }); |
| 20181 | 20181 | |
| 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); | |
| 20184 | 20184 | |
| 20185 | 20185 | const operand_info = [2]std.meta.Tuple(&.{ u64, LazySrcLoc, Type }){ |
| 20186 | 20186 | .{ a_len, a_src, a_ty }, |
| ... | ... | @@ -27503,9 +27503,6 @@ fn analyzeLoad( |
| 27503 | 27503 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { |
| 27504 | 27504 | return sema.addConstant(elem_ty, elem_val); |
| 27505 | 27505 | } |
| 27506 | if (block.is_typeof) { | |
| 27507 | return sema.addConstUndef(elem_ty); | |
| 27508 | } | |
| 27509 | 27506 | } |
| 27510 | 27507 | |
| 27511 | 27508 | return block.addTyOp(.load, elem_ty, ptr); |
src/codegen/llvm.zig+17-14| ... | ... | @@ -1966,7 +1966,7 @@ pub const Object = struct { |
| 1966 | 1966 | |
| 1967 | 1967 | for (tuple.types) |field_ty, i| { |
| 1968 | 1968 | 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; | |
| 1970 | 1970 | |
| 1971 | 1971 | const field_size = field_ty.abiSize(target); |
| 1972 | 1972 | const field_align = field_ty.abiAlignment(target); |
| ... | ... | @@ -2901,7 +2901,7 @@ pub const DeclGen = struct { |
| 2901 | 2901 | |
| 2902 | 2902 | for (tuple.types) |field_ty, i| { |
| 2903 | 2903 | 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; | |
| 2905 | 2905 | |
| 2906 | 2906 | const field_align = field_ty.abiAlignment(target); |
| 2907 | 2907 | big_align = @max(big_align, field_align); |
| ... | ... | @@ -3198,7 +3198,8 @@ pub const DeclGen = struct { |
| 3198 | 3198 | /// There are other similar cases handled here as well. |
| 3199 | 3199 | fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type { |
| 3200 | 3200 | const lower_elem_ty = switch (elem_ty.zigTypeTag()) { |
| 3201 | .Opaque, .Fn => true, | |
| 3201 | .Opaque => true, | |
| 3202 | .Fn => !elem_ty.fnInfo().is_generic, | |
| 3202 | 3203 | .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), |
| 3203 | 3204 | else => elem_ty.hasRuntimeBitsIgnoreComptime(), |
| 3204 | 3205 | }; |
| ... | ... | @@ -4145,7 +4146,9 @@ pub const DeclGen = struct { |
| 4145 | 4146 | } |
| 4146 | 4147 | |
| 4147 | 4148 | 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 | { | |
| 4149 | 4152 | return self.lowerPtrToVoid(tv.ty); |
| 4150 | 4153 | } |
| 4151 | 4154 | |
| ... | ... | @@ -8671,9 +8674,9 @@ pub const FuncGen = struct { |
| 8671 | 8674 | const arena = arena_allocator.allocator(); |
| 8672 | 8675 | |
| 8673 | 8676 | 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}); | |
| 8677 | 8680 | |
| 8678 | 8681 | var int_tag_type_buffer: Type.Payload.Bits = undefined; |
| 8679 | 8682 | const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer); |
| ... | ... | @@ -8752,9 +8755,9 @@ pub const FuncGen = struct { |
| 8752 | 8755 | const arena = arena_allocator.allocator(); |
| 8753 | 8756 | |
| 8754 | 8757 | 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}); | |
| 8758 | 8761 | |
| 8759 | 8762 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 8760 | 8763 | const llvm_ret_ty = try self.dg.lowerType(slice_ty); |
| ... | ... | @@ -10204,7 +10207,7 @@ fn llvmFieldIndex( |
| 10204 | 10207 | const tuple = ty.tupleFields(); |
| 10205 | 10208 | var llvm_field_index: c_uint = 0; |
| 10206 | 10209 | 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; | |
| 10208 | 10211 | |
| 10209 | 10212 | const field_align = field_ty.abiAlignment(target); |
| 10210 | 10213 | big_align = @max(big_align, field_align); |
| ... | ... | @@ -10216,7 +10219,7 @@ fn llvmFieldIndex( |
| 10216 | 10219 | llvm_field_index += 1; |
| 10217 | 10220 | } |
| 10218 | 10221 | |
| 10219 | if (field_index == i) { | |
| 10222 | if (field_index <= i) { | |
| 10220 | 10223 | ptr_pl_buf.* = .{ |
| 10221 | 10224 | .data = .{ |
| 10222 | 10225 | .pointee_type = field_ty, |
| ... | ... | @@ -10249,7 +10252,7 @@ fn llvmFieldIndex( |
| 10249 | 10252 | llvm_field_index += 1; |
| 10250 | 10253 | } |
| 10251 | 10254 | |
| 10252 | if (field_index == i) { | |
| 10255 | if (field_index <= i) { | |
| 10253 | 10256 | ptr_pl_buf.* = .{ |
| 10254 | 10257 | .data = .{ |
| 10255 | 10258 | .pointee_type = field.ty, |
| ... | ... | @@ -10768,7 +10771,7 @@ fn isByRef(ty: Type) bool { |
| 10768 | 10771 | const tuple = ty.tupleFields(); |
| 10769 | 10772 | var count: usize = 0; |
| 10770 | 10773 | 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; | |
| 10772 | 10775 | |
| 10773 | 10776 | count += 1; |
| 10774 | 10777 | if (count > max_fields_byval) return true; |
src/type.zig+4-2| ... | ... | @@ -640,7 +640,9 @@ pub const Type = extern union { |
| 640 | 640 | const a_info = a.fnInfo(); |
| 641 | 641 | const b_info = b.fnInfo(); |
| 642 | 642 | |
| 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)) | |
| 644 | 646 | return false; |
| 645 | 647 | |
| 646 | 648 | if (a_info.is_var_args != b_info.is_var_args) |
| ... | ... | @@ -5757,7 +5759,7 @@ pub const Type = extern union { |
| 5757 | 5759 | |
| 5758 | 5760 | for (tuple.types) |field_ty, i| { |
| 5759 | 5761 | const field_val = tuple.values[i]; |
| 5760 | if (field_val.tag() != .unreachable_value) { | |
| 5762 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) { | |
| 5761 | 5763 | // comptime field |
| 5762 | 5764 | if (i == index) return offset; |
| 5763 | 5765 | continue; |
test/behavior/eval.zig+8| ... | ... | @@ -1499,3 +1499,11 @@ test "non-optional and optional array elements concatenated" { |
| 1499 | 1499 | var index: usize = 0; |
| 1500 | 1500 | try expect(array[index].? == 'A'); |
| 1501 | 1501 | } |
| 1502 | ||
| 1503 | test "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" { |
| 405 | 405 | }; |
| 406 | 406 | try S.doTheTest((@intToPtr([*:null]const [*c]const u8, 8))); |
| 407 | 407 | } |
| 408 | ||
| 409 | test "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" { |
| 489 | 489 | var p = @ptrCast([*c]const u8, s); |
| 490 | 490 | try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0)); |
| 491 | 491 | } |
| 492 | ||
| 493 | test "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" { |
| 1398 | 1398 | const result = std.mem.readIntNative(u64, array[4..12]); |
| 1399 | 1399 | try expect(result == 1234); |
| 1400 | 1400 | } |
| 1401 | ||
| 1402 | test "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" { |
| 323 | 323 | var s: State = undefined; |
| 324 | 324 | try expect(s.do() == 0); |
| 325 | 325 | } |
| 326 | ||
| 327 | test "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 { |
| 75 | 75 | const a = AA.b(42); |
| 76 | 76 | try expect(a.x == AA.c().expected); |
| 77 | 77 | } |
| 78 | ||
| 79 | comptime { | |
| 80 | _ = @import("usingnamespace/file_1.zig"); | |
| 81 | } |
test/behavior/usingnamespace/file_0.zig created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | pub const A = 123; |
test/behavior/usingnamespace/file_1.zig created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | const imports = @import("imports.zig"); | |
| 4 | ||
| 5 | const A = 456; | |
| 6 | ||
| 7 | test { | |
| 8 | try expect(imports.A == 123); | |
| 9 | } |
test/behavior/usingnamespace/imports.zig created+5| ... | ... | @@ -0,0 +1,5 @@ |
| 1 | const file_0 = @import("file_0.zig"); | |
| 2 | const file_1 = @import("file_1.zig"); | |
| 3 | ||
| 4 | pub usingnamespace file_0; | |
| 5 | pub usingnamespace file_1; |
test/behavior/vector.zig+15| ... | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | 3 | const mem = std.mem; |
| 4 | 4 | const math = std.math; |
| 5 | 5 | const expect = std.testing.expect; |
| 6 | const expectEqual = std.testing.expectEqual; | |
| 6 | 7 | |
| 7 | 8 | test "implicit cast vector to array - bool" { |
| 8 | 9 | if (builtin.zig_backend == .stage1) { |
| ... | ... | @@ -1231,3 +1232,17 @@ test "modRem with zero divisor" { |
| 1231 | 1232 | _ = zeros[0]; |
| 1232 | 1233 | } |
| 1233 | 1234 | } |
| 1235 | ||
| 1236 | test "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 @@ |
| 1 | pub 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 | ||
| 8 | pub 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 { |
| 3 | 3 | x += 1; |
| 4 | 4 | _ = x; |
| 5 | 5 | } |
| 6 | export fn bar() void { | |
| 7 | var b: u32 = 1; | |
| 8 | _ = blk: { | |
| 9 | const a = 1; | |
| 10 | b = a; | |
| 11 | break :blk a; | |
| 12 | }; | |
| 13 | } | |
| 6 | 14 | |
| 7 | 15 | // error |
| 8 | 16 | // backend=stage2 |