| author | |
| committer | |
| log | b3aa1ab693ac160a07c44f07c7b90577039860a1 |
| tree | 6c5f4bf623b276963cec98ebbf713d2a752e9e01 |
| parent | db82c1b9820449f2d1e6ef54dd32ec3ffd3c583f |
| parent | 315d4e84425ddff888de8d464f657981e4c45da7 |
| signature |
stage2: `@TypeOf` improvements7 files changed, 158 insertions(+), 52 deletions(-)
src/AstGen.zig+41-15| ... | @@ -2159,6 +2159,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner | ... | @@ -2159,6 +2159,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2159 | .negate, | 2159 | .negate, |
| 2160 | .negate_wrap, | 2160 | .negate_wrap, |
| 2161 | .typeof, | 2161 | .typeof, |
| 2162 | .typeof_builtin, | ||
| 2162 | .xor, | 2163 | .xor, |
| 2163 | .optional_type, | 2164 | .optional_type, |
| 2164 | .optional_payload_safe, | 2165 | .optional_payload_safe, |
| ... | @@ -6875,29 +6876,54 @@ fn typeOf( | ... | @@ -6875,29 +6876,54 @@ fn typeOf( |
| 6875 | scope: *Scope, | 6876 | scope: *Scope, |
| 6876 | rl: ResultLoc, | 6877 | rl: ResultLoc, |
| 6877 | node: Ast.Node.Index, | 6878 | node: Ast.Node.Index, |
| 6878 | params: []const Ast.Node.Index, | 6879 | args: []const Ast.Node.Index, |
| 6879 | ) InnerError!Zir.Inst.Ref { | 6880 | ) InnerError!Zir.Inst.Ref { |
| 6880 | if (params.len < 1) { | 6881 | if (args.len < 1) { |
| 6881 | return gz.astgen.failNode(node, "expected at least 1 argument, found 0", .{}); | 6882 | return gz.astgen.failNode(node, "expected at least 1 argument, found 0", .{}); |
| 6882 | } | 6883 | } |
| 6883 | if (params.len == 1) { | 6884 | const gpa = gz.astgen.gpa; |
| 6884 | const expr_result = try reachableExpr(gz, scope, .none, params[0], node); | 6885 | if (args.len == 1) { |
| 6885 | const result = try gz.addUnNode(.typeof, expr_result, node); | 6886 | const typeof_inst = try gz.makeBlockInst(.typeof_builtin, node); |
| 6886 | return rvalue(gz, rl, result, node); | 6887 | |
| 6888 | var typeof_scope = gz.makeSubBlock(scope); | ||
| 6889 | typeof_scope.force_comptime = false; | ||
| 6890 | defer typeof_scope.unstack(); | ||
| 6891 | |||
| 6892 | const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, args[0], node); | ||
| 6893 | if (!gz.refIsNoReturn(ty_expr)) { | ||
| 6894 | _ = try typeof_scope.addBreak(.break_inline, typeof_inst, ty_expr); | ||
| 6895 | } | ||
| 6896 | try typeof_scope.setBlockBody(typeof_inst); | ||
| 6897 | |||
| 6898 | // typeof_scope unstacked now, can add new instructions to gz | ||
| 6899 | try gz.instructions.append(gpa, typeof_inst); | ||
| 6900 | return rvalue(gz, rl, indexToRef(typeof_inst), node); | ||
| 6887 | } | 6901 | } |
| 6902 | const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len; | ||
| 6903 | const payload_index = try reserveExtra(gz.astgen, payload_size + args.len); | ||
| 6904 | var args_index = payload_index + payload_size; | ||
| 6905 | |||
| 6906 | const typeof_inst = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, args.len); | ||
| 6888 | 6907 | ||
| 6889 | const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{ | 6908 | var typeof_scope = gz.makeSubBlock(scope); |
| 6909 | typeof_scope.force_comptime = false; | ||
| 6910 | |||
| 6911 | for (args) |arg, i| { | ||
| 6912 | const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, arg, node); | ||
| 6913 | gz.astgen.extra.items[args_index + i] = @enumToInt(param_ref); | ||
| 6914 | } | ||
| 6915 | _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value); | ||
| 6916 | |||
| 6917 | const body = typeof_scope.instructionsSlice(); | ||
| 6918 | gz.astgen.setExtra(payload_index, Zir.Inst.TypeOfPeer{ | ||
| 6919 | .body_len = @intCast(u32, body.len), | ||
| 6920 | .body_index = @intCast(u32, gz.astgen.extra.items.len), | ||
| 6890 | .src_node = gz.nodeIndexToRelative(node), | 6921 | .src_node = gz.nodeIndexToRelative(node), |
| 6891 | }); | 6922 | }); |
| 6892 | var extra_index = try reserveExtra(gz.astgen, params.len); | 6923 | try gz.astgen.extra.appendSlice(gpa, body); |
| 6893 | for (params) |param| { | 6924 | typeof_scope.unstack(); |
| 6894 | const param_ref = try reachableExpr(gz, scope, .none, param, node); | ||
| 6895 | gz.astgen.extra.items[extra_index] = @enumToInt(param_ref); | ||
| 6896 | extra_index += 1; | ||
| 6897 | } | ||
| 6898 | 6925 | ||
| 6899 | const result = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, params.len); | 6926 | return rvalue(gz, rl, typeof_inst, node); |
| 6900 | return rvalue(gz, rl, result, node); | ||
| 6901 | } | 6927 | } |
| 6902 | 6928 | ||
| 6903 | fn builtinCall( | 6929 | fn builtinCall( |
src/Sema.zig+46-3| ... | @@ -124,6 +124,7 @@ pub const Block = struct { | ... | @@ -124,6 +124,7 @@ pub const Block = struct { |
| 124 | runtime_index: u32 = 0, | 124 | runtime_index: u32 = 0, |
| 125 | 125 | ||
| 126 | is_comptime: bool, | 126 | is_comptime: bool, |
| 127 | is_typeof: bool = false, | ||
| 127 | 128 | ||
| 128 | /// when null, it is determined by build mode, changed by @setRuntimeSafety | 129 | /// when null, it is determined by build mode, changed by @setRuntimeSafety |
| 129 | want_safety: ?bool = null, | 130 | want_safety: ?bool = null, |
| ... | @@ -181,6 +182,7 @@ pub const Block = struct { | ... | @@ -181,6 +182,7 @@ pub const Block = struct { |
| 181 | .label = null, | 182 | .label = null, |
| 182 | .inlining = parent.inlining, | 183 | .inlining = parent.inlining, |
| 183 | .is_comptime = parent.is_comptime, | 184 | .is_comptime = parent.is_comptime, |
| 185 | .is_typeof = parent.is_typeof, | ||
| 184 | .runtime_cond = parent.runtime_cond, | 186 | .runtime_cond = parent.runtime_cond, |
| 185 | .runtime_loop = parent.runtime_loop, | 187 | .runtime_loop = parent.runtime_loop, |
| 186 | .runtime_index = parent.runtime_index, | 188 | .runtime_index = parent.runtime_index, |
| ... | @@ -682,6 +684,7 @@ fn analyzeBodyInner( | ... | @@ -682,6 +684,7 @@ fn analyzeBodyInner( |
| 682 | .size_of => try sema.zirSizeOf(block, inst), | 684 | .size_of => try sema.zirSizeOf(block, inst), |
| 683 | .bit_size_of => try sema.zirBitSizeOf(block, inst), | 685 | .bit_size_of => try sema.zirBitSizeOf(block, inst), |
| 684 | .typeof => try sema.zirTypeof(block, inst), | 686 | .typeof => try sema.zirTypeof(block, inst), |
| 687 | .typeof_builtin => try sema.zirTypeofBuiltin(block, inst), | ||
| 685 | .log2_int_type => try sema.zirLog2IntType(block, inst), | 688 | .log2_int_type => try sema.zirLog2IntType(block, inst), |
| 686 | .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst), | 689 | .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst), |
| 687 | .xor => try sema.zirBitwise(block, inst, .xor), | 690 | .xor => try sema.zirBitwise(block, inst, .xor), |
| ... | @@ -10574,6 +10577,29 @@ fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -10574,6 +10577,29 @@ fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 10574 | return sema.addType(operand_ty); | 10577 | return sema.addType(operand_ty); |
| 10575 | } | 10578 | } |
| 10576 | 10579 | ||
| 10580 | fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | ||
| 10581 | const pl_node = sema.code.instructions.items(.data)[inst].pl_node; | ||
| 10582 | const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index); | ||
| 10583 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; | ||
| 10584 | |||
| 10585 | var child_block: Block = .{ | ||
| 10586 | .parent = block, | ||
| 10587 | .sema = sema, | ||
| 10588 | .src_decl = block.src_decl, | ||
| 10589 | .namespace = block.namespace, | ||
| 10590 | .wip_capture_scope = block.wip_capture_scope, | ||
| 10591 | .instructions = .{}, | ||
| 10592 | .inlining = block.inlining, | ||
| 10593 | .is_comptime = false, | ||
| 10594 | .is_typeof = true, | ||
| 10595 | }; | ||
| 10596 | defer child_block.instructions.deinit(sema.gpa); | ||
| 10597 | |||
| 10598 | const operand = try sema.resolveBody(&child_block, body, inst); | ||
| 10599 | const operand_ty = sema.typeOf(operand); | ||
| 10600 | return sema.addType(operand_ty); | ||
| 10601 | } | ||
| 10602 | |||
| 10577 | fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 10603 | fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 10578 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 10604 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 10579 | const src = inst_data.src(); | 10605 | const src = inst_data.src(); |
| ... | @@ -10624,8 +10650,24 @@ fn zirTypeofPeer( | ... | @@ -10624,8 +10650,24 @@ fn zirTypeofPeer( |
| 10624 | const tracy = trace(@src()); | 10650 | const tracy = trace(@src()); |
| 10625 | defer tracy.end(); | 10651 | defer tracy.end(); |
| 10626 | 10652 | ||
| 10627 | const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); | 10653 | const extra = sema.code.extraData(Zir.Inst.TypeOfPeer, extended.operand); |
| 10628 | const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; | 10654 | const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; |
| 10655 | const body = sema.code.extra[extra.data.body_index..][0..extra.data.body_len]; | ||
| 10656 | |||
| 10657 | var child_block: Block = .{ | ||
| 10658 | .parent = block, | ||
| 10659 | .sema = sema, | ||
| 10660 | .src_decl = block.src_decl, | ||
| 10661 | .namespace = block.namespace, | ||
| 10662 | .wip_capture_scope = block.wip_capture_scope, | ||
| 10663 | .instructions = .{}, | ||
| 10664 | .inlining = block.inlining, | ||
| 10665 | .is_comptime = false, | ||
| 10666 | .is_typeof = true, | ||
| 10667 | }; | ||
| 10668 | defer child_block.instructions.deinit(sema.gpa); | ||
| 10669 | _ = try sema.analyzeBody(&child_block, body); | ||
| 10670 | |||
| 10629 | const args = sema.code.refSlice(extra.end, extended.small); | 10671 | const args = sema.code.refSlice(extra.end, extended.small); |
| 10630 | 10672 | ||
| 10631 | const inst_list = try sema.gpa.alloc(Air.Inst.Ref, args.len); | 10673 | const inst_list = try sema.gpa.alloc(Air.Inst.Ref, args.len); |
| ... | @@ -13385,7 +13427,7 @@ fn zirBuiltinExtern( | ... | @@ -13385,7 +13427,7 @@ fn zirBuiltinExtern( |
| 13385 | } | 13427 | } |
| 13386 | 13428 | ||
| 13387 | fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void { | 13429 | fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void { |
| 13388 | if (sema.func == null) { | 13430 | if (sema.func == null and !block.is_typeof) { |
| 13389 | return sema.fail(block, src, "instruction illegal outside function body", .{}); | 13431 | return sema.fail(block, src, "instruction illegal outside function body", .{}); |
| 13390 | } | 13432 | } |
| 13391 | } | 13433 | } |
| ... | @@ -14152,7 +14194,8 @@ fn fieldCallBind( | ... | @@ -14152,7 +14194,8 @@ fn fieldCallBind( |
| 14152 | if (first_param_tag == .var_args_param or | 14194 | if (first_param_tag == .var_args_param or |
| 14153 | first_param_tag == .generic_poison or ( | 14195 | first_param_tag == .generic_poison or ( |
| 14154 | first_param_type.zigTypeTag() == .Pointer and | 14196 | first_param_type.zigTypeTag() == .Pointer and |
| 14155 | first_param_type.ptrSize() == .One and | 14197 | (first_param_type.ptrSize() == .One or |
| 14198 | first_param_type.ptrSize() == .C) and | ||
| 14156 | first_param_type.childType().eql(concrete_ty))) | 14199 | first_param_type.childType().eql(concrete_ty))) |
| 14157 | { | 14200 | { |
| 14158 | // zig fmt: on | 14201 | // zig fmt: on |
src/Zir.zig+11| ... | @@ -547,6 +547,9 @@ pub const Inst = struct { | ... | @@ -547,6 +547,9 @@ pub const Inst = struct { |
| 547 | /// Returns the type of a value. | 547 | /// Returns the type of a value. |
| 548 | /// Uses the `un_node` field. | 548 | /// Uses the `un_node` field. |
| 549 | typeof, | 549 | typeof, |
| 550 | /// Implements `@TypeOf` for one operand. | ||
| 551 | /// Uses the `pl_node` field. | ||
| 552 | typeof_builtin, | ||
| 550 | /// Given a value, look at the type of it, which must be an integer type. | 553 | /// Given a value, look at the type of it, which must be an integer type. |
| 551 | /// Returns the integer type for the RHS of a shift operation. | 554 | /// Returns the integer type for the RHS of a shift operation. |
| 552 | /// Uses the `un_node` field. | 555 | /// Uses the `un_node` field. |
| ... | @@ -1067,6 +1070,7 @@ pub const Inst = struct { | ... | @@ -1067,6 +1070,7 @@ pub const Inst = struct { |
| 1067 | .negate, | 1070 | .negate, |
| 1068 | .negate_wrap, | 1071 | .negate_wrap, |
| 1069 | .typeof, | 1072 | .typeof, |
| 1073 | .typeof_builtin, | ||
| 1070 | .xor, | 1074 | .xor, |
| 1071 | .optional_type, | 1075 | .optional_type, |
| 1072 | .optional_payload_safe, | 1076 | .optional_payload_safe, |
| ... | @@ -1429,6 +1433,7 @@ pub const Inst = struct { | ... | @@ -1429,6 +1433,7 @@ pub const Inst = struct { |
| 1429 | .ptr_cast = .pl_node, | 1433 | .ptr_cast = .pl_node, |
| 1430 | .truncate = .pl_node, | 1434 | .truncate = .pl_node, |
| 1431 | .align_cast = .pl_node, | 1435 | .align_cast = .pl_node, |
| 1436 | .typeof_builtin = .pl_node, | ||
| 1432 | 1437 | ||
| 1433 | .has_decl = .pl_node, | 1438 | .has_decl = .pl_node, |
| 1434 | .has_field = .pl_node, | 1439 | .has_field = .pl_node, |
| ... | @@ -2391,6 +2396,12 @@ pub const Inst = struct { | ... | @@ -2391,6 +2396,12 @@ pub const Inst = struct { |
| 2391 | }; | 2396 | }; |
| 2392 | }; | 2397 | }; |
| 2393 | 2398 | ||
| 2399 | pub const TypeOfPeer = struct { | ||
| 2400 | src_node: i32, | ||
| 2401 | body_len: u32, | ||
| 2402 | body_index: u32, | ||
| 2403 | }; | ||
| 2404 | |||
| 2394 | pub const BuiltinCall = struct { | 2405 | pub const BuiltinCall = struct { |
| 2395 | options: Ref, | 2406 | options: Ref, |
| 2396 | callee: Ref, | 2407 | callee: Ref, |
src/print_zir.zig+16-3| ... | @@ -374,6 +374,7 @@ const Writer = struct { | ... | @@ -374,6 +374,7 @@ const Writer = struct { |
| 374 | .validate_array_init, | 374 | .validate_array_init, |
| 375 | .validate_array_init_comptime, | 375 | .validate_array_init_comptime, |
| 376 | .c_import, | 376 | .c_import, |
| 377 | .typeof_builtin, | ||
| 377 | => try self.writePlNodeBlock(stream, inst), | 378 | => try self.writePlNodeBlock(stream, inst), |
| 378 | 379 | ||
| 379 | .condbr, | 380 | .condbr, |
| ... | @@ -458,9 +459,8 @@ const Writer = struct { | ... | @@ -458,9 +459,8 @@ const Writer = struct { |
| 458 | .variable => try self.writeVarExtended(stream, extended), | 459 | .variable => try self.writeVarExtended(stream, extended), |
| 459 | .alloc => try self.writeAllocExtended(stream, extended), | 460 | .alloc => try self.writeAllocExtended(stream, extended), |
| 460 | 461 | ||
| 461 | .compile_log, | 462 | .compile_log => try self.writeNodeMultiOp(stream, extended), |
| 462 | .typeof_peer, | 463 | .typeof_peer => try self.writeTypeofPeer(stream, extended), |
| 463 | => try self.writeNodeMultiOp(stream, extended), | ||
| 464 | 464 | ||
| 465 | .add_with_overflow, | 465 | .add_with_overflow, |
| 466 | .sub_with_overflow, | 466 | .sub_with_overflow, |
| ... | @@ -1966,6 +1966,19 @@ const Writer = struct { | ... | @@ -1966,6 +1966,19 @@ const Writer = struct { |
| 1966 | try self.writeSrc(stream, src); | 1966 | try self.writeSrc(stream, src); |
| 1967 | } | 1967 | } |
| 1968 | 1968 | ||
| 1969 | fn writeTypeofPeer(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | ||
| 1970 | const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand); | ||
| 1971 | const body = self.code.extra[extra.data.body_index..][0..extra.data.body_len]; | ||
| 1972 | try self.writeBracedBody(stream, body); | ||
| 1973 | try stream.writeAll(",["); | ||
| 1974 | const args = self.code.refSlice(extra.end, extended.small); | ||
| 1975 | for (args) |arg, i| { | ||
| 1976 | if (i != 0) try stream.writeAll(", "); | ||
| 1977 | try self.writeInstRef(stream, arg); | ||
| 1978 | } | ||
| 1979 | try stream.writeAll("])"); | ||
| 1980 | } | ||
| 1981 | |||
| 1969 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | 1982 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
| 1970 | const inst_data = self.code.instructions.items(.data)[inst].bool_br; | 1983 | const inst_data = self.code.instructions.items(.data)[inst].bool_br; |
| 1971 | const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index); | 1984 | const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index); |
test/behavior.zig+2-2| ... | @@ -38,6 +38,7 @@ test { | ... | @@ -38,6 +38,7 @@ test { |
| 38 | _ = @import("behavior/bugs/3112.zig"); | 38 | _ = @import("behavior/bugs/3112.zig"); |
| 39 | _ = @import("behavior/bugs/3367.zig"); | 39 | _ = @import("behavior/bugs/3367.zig"); |
| 40 | _ = @import("behavior/bugs/3586.zig"); | 40 | _ = @import("behavior/bugs/3586.zig"); |
| 41 | _ = @import("behavior/bugs/4328.zig"); | ||
| 41 | _ = @import("behavior/bugs/4560.zig"); | 42 | _ = @import("behavior/bugs/4560.zig"); |
| 42 | _ = @import("behavior/bugs/4769_a.zig"); | 43 | _ = @import("behavior/bugs/4769_a.zig"); |
| 43 | _ = @import("behavior/bugs/4769_b.zig"); | 44 | _ = @import("behavior/bugs/4769_b.zig"); |
| ... | @@ -102,6 +103,7 @@ test { | ... | @@ -102,6 +103,7 @@ test { |
| 102 | builtin.zig_backend != .stage2_wasm) | 103 | builtin.zig_backend != .stage2_wasm) |
| 103 | { | 104 | { |
| 104 | // Tests that pass for stage1, llvm backend, C backend | 105 | // Tests that pass for stage1, llvm backend, C backend |
| 106 | _ = @import("behavior/bugs/5474.zig"); | ||
| 105 | _ = @import("behavior/bugs/9584.zig"); | 107 | _ = @import("behavior/bugs/9584.zig"); |
| 106 | _ = @import("behavior/bugs/10970.zig"); | 108 | _ = @import("behavior/bugs/10970.zig"); |
| 107 | _ = @import("behavior/cast_int.zig"); | 109 | _ = @import("behavior/cast_int.zig"); |
| ... | @@ -149,10 +151,8 @@ test { | ... | @@ -149,10 +151,8 @@ test { |
| 149 | _ = @import("behavior/bugs/1851.zig"); | 151 | _ = @import("behavior/bugs/1851.zig"); |
| 150 | _ = @import("behavior/bugs/3384.zig"); | 152 | _ = @import("behavior/bugs/3384.zig"); |
| 151 | _ = @import("behavior/bugs/3779.zig"); | 153 | _ = @import("behavior/bugs/3779.zig"); |
| 152 | _ = @import("behavior/bugs/4328.zig"); | ||
| 153 | _ = @import("behavior/bugs/5398.zig"); | 154 | _ = @import("behavior/bugs/5398.zig"); |
| 154 | _ = @import("behavior/bugs/5413.zig"); | 155 | _ = @import("behavior/bugs/5413.zig"); |
| 155 | _ = @import("behavior/bugs/5474.zig"); | ||
| 156 | _ = @import("behavior/bugs/5487.zig"); | 156 | _ = @import("behavior/bugs/5487.zig"); |
| 157 | _ = @import("behavior/bugs/6456.zig"); | 157 | _ = @import("behavior/bugs/6456.zig"); |
| 158 | _ = @import("behavior/bugs/6781.zig"); | 158 | _ = @import("behavior/bugs/6781.zig"); |
test/behavior/bugs/4328.zig+16-7| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const expectEqual = @import("std").testing.expectEqual; | 1 | const expect = @import("std").testing.expect; |
| 2 | const builtin = @import("builtin"); | ||
| 2 | 3 | ||
| 3 | const FILE = extern struct { | 4 | const FILE = extern struct { |
| 4 | dummy_field: u8, | 5 | dummy_field: u8, |
| ... | @@ -16,18 +17,20 @@ const S = extern struct { | ... | @@ -16,18 +17,20 @@ const S = extern struct { |
| 16 | }; | 17 | }; |
| 17 | 18 | ||
| 18 | test "Extern function calls in @TypeOf" { | 19 | test "Extern function calls in @TypeOf" { |
| 20 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 21 | |||
| 19 | const Test = struct { | 22 | const Test = struct { |
| 20 | fn test_fn_1(a: anytype, b: anytype) @TypeOf(printf("%d %s\n", a, b)) { | 23 | fn test_fn_1(a: anytype, b: anytype) @TypeOf(printf("%d %s\n", a, b)) { |
| 21 | return 0; | 24 | return 0; |
| 22 | } | 25 | } |
| 23 | 26 | ||
| 24 | fn test_fn_2(a: anytype) @TypeOf((S{ .state = 0 }).s_do_thing(a)) { | 27 | fn test_fn_2(s: anytype, a: anytype) @TypeOf(s.s_do_thing(a)) { |
| 25 | return 1; | 28 | return 1; |
| 26 | } | 29 | } |
| 27 | 30 | ||
| 28 | fn doTheTest() !void { | 31 | fn doTheTest() !void { |
| 29 | try expectEqual(c_int, @TypeOf(test_fn_1(0, 42))); | 32 | try expect(@TypeOf(test_fn_1(0, 42)) == c_int); |
| 30 | try expectEqual(c_short, @TypeOf(test_fn_2(0))); | 33 | try expect(@TypeOf(test_fn_2(&S{ .state = 1 }, 0)) == c_short); |
| 31 | } | 34 | } |
| 32 | }; | 35 | }; |
| 33 | 36 | ||
| ... | @@ -36,13 +39,15 @@ test "Extern function calls in @TypeOf" { | ... | @@ -36,13 +39,15 @@ test "Extern function calls in @TypeOf" { |
| 36 | } | 39 | } |
| 37 | 40 | ||
| 38 | test "Peer resolution of extern function calls in @TypeOf" { | 41 | test "Peer resolution of extern function calls in @TypeOf" { |
| 42 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 43 | |||
| 39 | const Test = struct { | 44 | const Test = struct { |
| 40 | fn test_fn() @TypeOf(ftell(null), fputs(null, null)) { | 45 | fn test_fn() @TypeOf(ftell(null), fputs(null, null)) { |
| 41 | return 0; | 46 | return 0; |
| 42 | } | 47 | } |
| 43 | 48 | ||
| 44 | fn doTheTest() !void { | 49 | fn doTheTest() !void { |
| 45 | try expectEqual(c_long, @TypeOf(test_fn())); | 50 | try expect(@TypeOf(test_fn()) == c_long); |
| 46 | } | 51 | } |
| 47 | }; | 52 | }; |
| 48 | 53 | ||
| ... | @@ -51,6 +56,10 @@ test "Peer resolution of extern function calls in @TypeOf" { | ... | @@ -51,6 +56,10 @@ test "Peer resolution of extern function calls in @TypeOf" { |
| 51 | } | 56 | } |
| 52 | 57 | ||
| 53 | test "Extern function calls, dereferences and field access in @TypeOf" { | 58 | test "Extern function calls, dereferences and field access in @TypeOf" { |
| 59 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 60 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 61 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 62 | |||
| 54 | const Test = struct { | 63 | const Test = struct { |
| 55 | fn test_fn_1(a: c_long) @TypeOf(fopen("test", "r").*) { | 64 | fn test_fn_1(a: c_long) @TypeOf(fopen("test", "r").*) { |
| 56 | _ = a; | 65 | _ = a; |
| ... | @@ -63,8 +72,8 @@ test "Extern function calls, dereferences and field access in @TypeOf" { | ... | @@ -63,8 +72,8 @@ test "Extern function calls, dereferences and field access in @TypeOf" { |
| 63 | } | 72 | } |
| 64 | 73 | ||
| 65 | fn doTheTest() !void { | 74 | fn doTheTest() !void { |
| 66 | try expectEqual(FILE, @TypeOf(test_fn_1(0))); | 75 | try expect(@TypeOf(test_fn_1(0)) == FILE); |
| 67 | try expectEqual(u8, @TypeOf(test_fn_2(0))); | 76 | try expect(@TypeOf(test_fn_2(0)) == u8); |
| 68 | } | 77 | } |
| 69 | }; | 78 | }; |
| 70 | 79 |
test/behavior/bugs/5474.zig+26-22| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | 3 | ||
| 3 | // baseline (control) struct with array of scalar | 4 | // baseline (control) struct with array of scalar |
| 4 | const Box0 = struct { | 5 | const Box0 = struct { |
| ... | @@ -25,33 +26,36 @@ const Box2 = struct { | ... | @@ -25,33 +26,36 @@ const Box2 = struct { |
| 25 | }; | 26 | }; |
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | fn doTest() !void { | 29 | fn mutable() !void { |
| 29 | // var | 30 | var box0: Box0 = .{ .items = undefined }; |
| 30 | { | 31 | try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == false); |
| 31 | var box0: Box0 = .{ .items = undefined }; | ||
| 32 | try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == false); | ||
| 33 | 32 | ||
| 34 | var box1: Box1 = .{ .items = undefined }; | 33 | var box1: Box1 = .{ .items = undefined }; |
| 35 | try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == false); | 34 | try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == false); |
| 36 | 35 | ||
| 37 | var box2: Box2 = .{ .items = undefined }; | 36 | var box2: Box2 = .{ .items = undefined }; |
| 38 | try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == false); | 37 | try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == false); |
| 39 | } | 38 | } |
| 39 | |||
| 40 | fn constant() !void { | ||
| 41 | const box0: Box0 = .{ .items = undefined }; | ||
| 42 | try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == true); | ||
| 40 | 43 | ||
| 41 | // const | 44 | const box1: Box1 = .{ .items = undefined }; |
| 42 | { | 45 | try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == true); |
| 43 | const box0: Box0 = .{ .items = undefined }; | ||
| 44 | try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == true); | ||
| 45 | 46 | ||
| 46 | const box1: Box1 = .{ .items = undefined }; | 47 | const box2: Box2 = .{ .items = undefined }; |
| 47 | try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == true); | 48 | try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == true); |
| 49 | } | ||
| 48 | 50 | ||
| 49 | const box2: Box2 = .{ .items = undefined }; | 51 | test "pointer-to-array constness for zero-size elements, var" { |
| 50 | try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == true); | 52 | try mutable(); |
| 51 | } | 53 | comptime try mutable(); |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 54 | test "pointer-to-array constness for zero-size elements" { | 56 | test "pointer-to-array constness for zero-size elements, const" { |
| 55 | try doTest(); | 57 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 56 | comptime try doTest(); | 58 | |
| 59 | try constant(); | ||
| 60 | comptime try constant(); | ||
| 57 | } | 61 | } |