| author | |
| committer | |
| log | 8667d6d61e8217159377c0e22bc35075848d1202 |
| tree | 4dd89f89f346d2a1f435efff54cd27d33485f2c5 |
| parent | f1999712b0a8560bd84726c8a5e8fd37dbdf5375 |
| parent | 5404dcdfd844e4b9f47dc49a1f43f0e1075a563f |
| signature |
Stage2 fixes20 files changed, 179 insertions(+), 37 deletions(-)
doc/langref.html.in+2-2| ... | ... | @@ -5024,8 +5024,8 @@ fn shiftLeftOne(a: u32) callconv(.Inline) u32 { |
| 5024 | 5024 | // Another file can use @import and call sub2 |
| 5025 | 5025 | pub fn sub2(a: i8, b: i8) i8 { return a - b; } |
| 5026 | 5026 | |
| 5027 | // Functions can be used as values and are equivalent to pointers. | |
| 5028 | const call2_op = fn (a: i8, b: i8) i8; | |
| 5027 | // Function pointers are prefixed with `*const `. | |
| 5028 | const call2_op = *const fn (a: i8, b: i8) i8; | |
| 5029 | 5029 | fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 { |
| 5030 | 5030 | return fn_call(op1, op2); |
| 5031 | 5031 | } |
lib/std/fs/path.zig+1-1| ... | ... | @@ -42,7 +42,7 @@ pub fn isSep(byte: u8) bool { |
| 42 | 42 | |
| 43 | 43 | /// This is different from mem.join in that the separator will not be repeated if |
| 44 | 44 | /// it is found at the end or beginning of a pair of consecutive paths. |
| 45 | fn joinSepMaybeZ(allocator: Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 { | |
| 45 | fn joinSepMaybeZ(allocator: Allocator, separator: u8, comptime sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 { | |
| 46 | 46 | if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{}; |
| 47 | 47 | |
| 48 | 48 | // Find first non-empty path index. |
lib/std/math.zig+1-1| ... | ... | @@ -1548,7 +1548,7 @@ test "boolMask" { |
| 1548 | 1548 | } |
| 1549 | 1549 | |
| 1550 | 1550 | /// Return the mod of `num` with the smallest integer type |
| 1551 | pub fn comptimeMod(num: anytype, denom: comptime_int) IntFittingRange(0, denom - 1) { | |
| 1551 | pub fn comptimeMod(num: anytype, comptime denom: comptime_int) IntFittingRange(0, denom - 1) { | |
| 1552 | 1552 | return @intCast(IntFittingRange(0, denom - 1), @mod(num, denom)); |
| 1553 | 1553 | } |
| 1554 | 1554 |
lib/std/math/float.zig+1-1| ... | ... | @@ -8,7 +8,7 @@ inline fn mantissaOne(comptime T: type) comptime_int { |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | 10 | /// Creates floating point type T from an unbiased exponent and raw mantissa. |
| 11 | inline fn reconstructFloat(comptime T: type, exponent: comptime_int, mantissa: comptime_int) T { | |
| 11 | inline fn reconstructFloat(comptime T: type, comptime exponent: comptime_int, comptime mantissa: comptime_int) T { | |
| 12 | 12 | const TBits = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); |
| 13 | 13 | const biased_exponent = @as(TBits, exponent + floatExponentMax(T)); |
| 14 | 14 | return @bitCast(T, (biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa)); |
lib/std/zig/c_translation.zig+1-1| ... | ... | @@ -349,7 +349,7 @@ test "shuffleVectorIndex" { |
| 349 | 349 | |
| 350 | 350 | /// Constructs a [*c] pointer with the const and volatile annotations |
| 351 | 351 | /// from SelfType for pointing to a C flexible array of ElementType. |
| 352 | pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type { | |
| 352 | pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) type { | |
| 353 | 353 | switch (@typeInfo(SelfType)) { |
| 354 | 354 | .Pointer => |ptr| { |
| 355 | 355 | return @Type(.{ .Pointer = .{ |
lib/std/zig/parse.zig+1-1| ... | ... | @@ -3670,7 +3670,7 @@ const Parser = struct { |
| 3670 | 3670 | } |
| 3671 | 3671 | |
| 3672 | 3672 | /// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)? |
| 3673 | fn parseIf(p: *Parser, bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index { | |
| 3673 | fn parseIf(p: *Parser, comptime bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index { | |
| 3674 | 3674 | const if_token = p.eatToken(.keyword_if) orelse return null_node; |
| 3675 | 3675 | _ = try p.expectToken(.l_paren); |
| 3676 | 3676 | const condition = try p.expectExpr(); |
src/Module.zig+4-4| ... | ... | @@ -6072,17 +6072,17 @@ pub fn paramSrc( |
| 6072 | 6072 | else => unreachable, |
| 6073 | 6073 | }; |
| 6074 | 6074 | var it = full.iterate(tree); |
| 6075 | while (true) { | |
| 6076 | if (it.param_i == param_i) { | |
| 6077 | const param = it.next().?; | |
| 6075 | var i: usize = 0; | |
| 6076 | while (it.next()) |param| : (i += 1) { | |
| 6077 | if (i == param_i) { | |
| 6078 | 6078 | if (param.anytype_ellipsis3) |some| { |
| 6079 | 6079 | const main_token = tree.nodes.items(.main_token)[decl.src_node]; |
| 6080 | 6080 | return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) }; |
| 6081 | 6081 | } |
| 6082 | 6082 | return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) }; |
| 6083 | 6083 | } |
| 6084 | _ = it.next(); | |
| 6085 | 6084 | } |
| 6085 | unreachable; | |
| 6086 | 6086 | } |
| 6087 | 6087 | |
| 6088 | 6088 | pub fn argSrc( |
src/Sema.zig+46-17| ... | ... | @@ -76,6 +76,8 @@ types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{}, |
| 76 | 76 | post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{}, |
| 77 | 77 | /// Populated with the last compile error created. |
| 78 | 78 | err: ?*Module.ErrorMsg = null, |
| 79 | /// True when analyzing a generic instantiation. Used to suppress some errors. | |
| 80 | is_generic_instantiation: bool = false, | |
| 79 | 81 | |
| 80 | 82 | const std = @import("std"); |
| 81 | 83 | const math = std.math; |
| ... | ... | @@ -1696,7 +1698,10 @@ fn resolveMaybeUndefValIntable( |
| 1696 | 1698 | .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr, |
| 1697 | 1699 | .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr, |
| 1698 | 1700 | .generic_poison => return error.GenericPoison, |
| 1699 | else => return val, | |
| 1701 | else => { | |
| 1702 | try sema.resolveLazyValue(block, src, val); | |
| 1703 | return val; | |
| 1704 | }, | |
| 1700 | 1705 | }; |
| 1701 | 1706 | } |
| 1702 | 1707 | |
| ... | ... | @@ -6495,6 +6500,7 @@ fn instantiateGenericCall( |
| 6495 | 6500 | .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len), |
| 6496 | 6501 | .comptime_args_fn_inst = module_fn.zir_body_inst, |
| 6497 | 6502 | .preallocated_new_func = new_module_func, |
| 6503 | .is_generic_instantiation = true, | |
| 6498 | 6504 | }; |
| 6499 | 6505 | defer child_sema.deinit(); |
| 6500 | 6506 | |
| ... | ... | @@ -7255,6 +7261,8 @@ fn zirOptionalPayload( |
| 7255 | 7261 | if (operand_ty.ptrSize() != .C) { |
| 7256 | 7262 | return sema.failWithExpectedOptionalType(block, src, operand_ty); |
| 7257 | 7263 | } |
| 7264 | // TODO https://github.com/ziglang/zig/issues/6597 | |
| 7265 | if (true) break :t operand_ty; | |
| 7258 | 7266 | const ptr_info = operand_ty.ptrInfo().data; |
| 7259 | 7267 | break :t try Type.ptr(sema.arena, sema.mod, .{ |
| 7260 | 7268 | .pointee_type = try ptr_info.pointee_type.copy(sema.arena), |
| ... | ... | @@ -7789,6 +7797,7 @@ fn funcCommon( |
| 7789 | 7797 | &is_generic, |
| 7790 | 7798 | is_extern, |
| 7791 | 7799 | cc_workaround, |
| 7800 | has_body, | |
| 7792 | 7801 | ) catch |err| switch (err) { |
| 7793 | 7802 | error.NeededSourceLocation => { |
| 7794 | 7803 | const decl = sema.mod.declPtr(block.src_decl); |
| ... | ... | @@ -7802,6 +7811,7 @@ fn funcCommon( |
| 7802 | 7811 | &is_generic, |
| 7803 | 7812 | is_extern, |
| 7804 | 7813 | cc_workaround, |
| 7814 | has_body, | |
| 7805 | 7815 | ); |
| 7806 | 7816 | return error.AnalysisFail; |
| 7807 | 7817 | }, |
| ... | ... | @@ -8005,6 +8015,7 @@ fn analyzeParameter( |
| 8005 | 8015 | is_generic: *bool, |
| 8006 | 8016 | is_extern: bool, |
| 8007 | 8017 | cc: std.builtin.CallingConvention, |
| 8018 | has_body: bool, | |
| 8008 | 8019 | ) !void { |
| 8009 | 8020 | const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty); |
| 8010 | 8021 | comptime_params[i] = param.is_comptime or requires_comptime; |
| ... | ... | @@ -8053,9 +8064,9 @@ fn analyzeParameter( |
| 8053 | 8064 | }; |
| 8054 | 8065 | return sema.failWithOwnedErrorMsg(msg); |
| 8055 | 8066 | } |
| 8056 | if (requires_comptime and !param.is_comptime) { | |
| 8067 | if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) { | |
| 8057 | 8068 | const msg = msg: { |
| 8058 | const msg = try sema.errMsg(block, param_src, "parametter of type '{}' must be declared comptime", .{ | |
| 8069 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{ | |
| 8059 | 8070 | param.ty.fmt(sema.mod), |
| 8060 | 8071 | }); |
| 8061 | 8072 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -8153,7 +8164,7 @@ fn zirParam( |
| 8153 | 8164 | |
| 8154 | 8165 | try block.params.append(sema.gpa, .{ |
| 8155 | 8166 | .ty = param_ty, |
| 8156 | .is_comptime = is_comptime, | |
| 8167 | .is_comptime = comptime_syntax, | |
| 8157 | 8168 | .name = param_name, |
| 8158 | 8169 | }); |
| 8159 | 8170 | const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison)); |
| ... | ... | @@ -16318,7 +16329,7 @@ fn zirUnaryMath( |
| 16318 | 16329 | block: *Block, |
| 16319 | 16330 | inst: Zir.Inst.Index, |
| 16320 | 16331 | air_tag: Air.Inst.Tag, |
| 16321 | eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value, | |
| 16332 | comptime eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value, | |
| 16322 | 16333 | ) CompileError!Air.Inst.Ref { |
| 16323 | 16334 | const tracy = trace(@src()); |
| 16324 | 16335 | defer tracy.end(); |
| ... | ... | @@ -17777,7 +17788,7 @@ fn zirBitCount( |
| 17777 | 17788 | block: *Block, |
| 17778 | 17789 | inst: Zir.Inst.Index, |
| 17779 | 17790 | air_tag: Air.Inst.Tag, |
| 17780 | comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64, | |
| 17791 | comptime comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64, | |
| 17781 | 17792 | ) CompileError!Air.Inst.Ref { |
| 17782 | 17793 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 17783 | 17794 | const src = inst_data.src(); |
| ... | ... | @@ -20554,8 +20565,8 @@ fn validatePackedType(ty: Type) bool { |
| 20554 | 20565 | .AnyFrame, |
| 20555 | 20566 | .Fn, |
| 20556 | 20567 | .Array, |
| 20557 | .Optional, | |
| 20558 | 20568 | => return false, |
| 20569 | .Optional => return ty.isPtrLikeOptional(), | |
| 20559 | 20570 | .Void, |
| 20560 | 20571 | .Bool, |
| 20561 | 20572 | .Float, |
| ... | ... | @@ -21383,14 +21394,30 @@ fn fieldCallBind( |
| 21383 | 21394 | switch (concrete_ty.zigTypeTag()) { |
| 21384 | 21395 | .Struct => { |
| 21385 | 21396 | const struct_ty = try sema.resolveTypeFields(block, src, concrete_ty); |
| 21386 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | |
| 21387 | ||
| 21388 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse | |
| 21389 | break :find_field; | |
| 21390 | const field_index = @intCast(u32, field_index_usize); | |
| 21391 | const field = struct_obj.fields.values()[field_index]; | |
| 21397 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | |
| 21398 | const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse | |
| 21399 | break :find_field; | |
| 21400 | const field_index = @intCast(u32, field_index_usize); | |
| 21401 | const field = struct_obj.data.fields.values()[field_index]; | |
| 21392 | 21402 | |
| 21393 | return finishFieldCallBind(sema, block, src, ptr_ty, field.ty, field_index, object_ptr); | |
| 21403 | return finishFieldCallBind(sema, block, src, ptr_ty, field.ty, field_index, object_ptr); | |
| 21404 | } else if (struct_ty.isTuple()) { | |
| 21405 | if (mem.eql(u8, field_name, "len")) { | |
| 21406 | return sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount()); | |
| 21407 | } | |
| 21408 | if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { | |
| 21409 | if (field_index >= struct_ty.structFieldCount()) break :find_field; | |
| 21410 | return finishFieldCallBind(sema, block, src, ptr_ty, struct_ty.structFieldType(field_index), field_index, object_ptr); | |
| 21411 | } else |_| {} | |
| 21412 | } else { | |
| 21413 | const max = struct_ty.structFieldCount(); | |
| 21414 | var i: u32 = 0; | |
| 21415 | while (i < max) : (i += 1) { | |
| 21416 | if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) { | |
| 21417 | return finishFieldCallBind(sema, block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr); | |
| 21418 | } | |
| 21419 | } | |
| 21420 | } | |
| 21394 | 21421 | }, |
| 21395 | 21422 | .Union => { |
| 21396 | 21423 | const union_ty = try sema.resolveTypeFields(block, src, concrete_ty); |
| ... | ... | @@ -22553,7 +22580,7 @@ fn coerceExtra( |
| 22553 | 22580 | // Function body to function pointer. |
| 22554 | 22581 | if (inst_ty.zigTypeTag() == .Fn) { |
| 22555 | 22582 | const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined); |
| 22556 | const fn_decl = fn_val.castTag(.function).?.data.owner_decl; | |
| 22583 | const fn_decl = fn_val.pointerDecl().?; | |
| 22557 | 22584 | const inst_as_ptr = try sema.analyzeDeclRef(fn_decl); |
| 22558 | 22585 | return sema.coerce(block, dest_ty, inst_as_ptr, inst_src); |
| 22559 | 22586 | } |
| ... | ... | @@ -27909,7 +27936,9 @@ fn resolveInferredErrorSetTy( |
| 27909 | 27936 | fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void { |
| 27910 | 27937 | const gpa = mod.gpa; |
| 27911 | 27938 | const decl_index = struct_obj.owner_decl; |
| 27912 | const zir = struct_obj.namespace.file_scope.zir; | |
| 27939 | const file_scope = struct_obj.namespace.file_scope; | |
| 27940 | if (file_scope.status != .success_zir) return error.AnalysisFail; | |
| 27941 | const zir = file_scope.zir; | |
| 27913 | 27942 | const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended; |
| 27914 | 27943 | assert(extended.opcode == .struct_decl); |
| 27915 | 27944 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| ... | ... | @@ -29489,7 +29518,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 29489 | 29518 | => { |
| 29490 | 29519 | const child_ty = ty.childType(); |
| 29491 | 29520 | if (child_ty.zigTypeTag() == .Fn) { |
| 29492 | return false; | |
| 29521 | return child_ty.fnInfo().is_generic; | |
| 29493 | 29522 | } else { |
| 29494 | 29523 | return sema.typeRequiresComptime(block, src, child_ty); |
| 29495 | 29524 | } |
src/codegen/llvm.zig+6-3| ... | ... | @@ -3417,7 +3417,10 @@ pub const DeclGen = struct { |
| 3417 | 3417 | }); |
| 3418 | 3418 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); |
| 3419 | 3419 | const small_int_ty = dg.context.intType(ty_bit_size); |
| 3420 | const small_int_val = non_int_val.constBitCast(small_int_ty); | |
| 3420 | const small_int_val = if (field.ty.isPtrAtRuntime()) | |
| 3421 | non_int_val.constPtrToInt(small_int_ty) | |
| 3422 | else | |
| 3423 | non_int_val.constBitCast(small_int_ty); | |
| 3421 | 3424 | const shift_rhs = int_llvm_ty.constInt(running_bits, .False); |
| 3422 | 3425 | // If the field is as large as the entire packed struct, this |
| 3423 | 3426 | // zext would go from, e.g. i16 to i16. This is legal with |
| ... | ... | @@ -5343,7 +5346,7 @@ pub const FuncGen = struct { |
| 5343 | 5346 | const same_size_int = self.context.intType(elem_bits); |
| 5344 | 5347 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 5345 | 5348 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 5346 | } else if (field_ty.zigTypeTag() == .Pointer) { | |
| 5349 | } else if (field_ty.isPtrAtRuntime()) { | |
| 5347 | 5350 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); |
| 5348 | 5351 | const same_size_int = self.context.intType(elem_bits); |
| 5349 | 5352 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| ... | ... | @@ -8408,7 +8411,7 @@ pub const FuncGen = struct { |
| 8408 | 8411 | const non_int_val = try self.resolveInst(elem); |
| 8409 | 8412 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); |
| 8410 | 8413 | const small_int_ty = self.dg.context.intType(ty_bit_size); |
| 8411 | const small_int_val = if (field.ty.zigTypeTag() == .Pointer) | |
| 8414 | const small_int_val = if (field.ty.isPtrAtRuntime()) | |
| 8412 | 8415 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 8413 | 8416 | else |
| 8414 | 8417 | self.builder.buildBitCast(non_int_val, small_int_ty, ""); |
src/type.zig+1-1| ... | ... | @@ -2394,7 +2394,7 @@ pub const Type = extern union { |
| 2394 | 2394 | if (ignore_comptime_only) { |
| 2395 | 2395 | return true; |
| 2396 | 2396 | } else if (ty.childType().zigTypeTag() == .Fn) { |
| 2397 | return true; | |
| 2397 | return !ty.childType().fnInfo().is_generic; | |
| 2398 | 2398 | } else if (sema_kit) |sk| { |
| 2399 | 2399 | return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty)); |
| 2400 | 2400 | } else { |
test/behavior/cast.zig+1-1| ... | ... | @@ -1281,7 +1281,7 @@ test "*const [N]null u8 to ?[]const u8" { |
| 1281 | 1281 | test "cast between [*c]T and ?[*:0]T on fn parameter" { |
| 1282 | 1282 | const S = struct { |
| 1283 | 1283 | const Handler = ?fn ([*c]const u8) callconv(.C) void; |
| 1284 | fn addCallback(handler: Handler) void { | |
| 1284 | fn addCallback(comptime handler: Handler) void { | |
| 1285 | 1285 | _ = handler; |
| 1286 | 1286 | } |
| 1287 | 1287 |
test/behavior/error.zig+1-1| ... | ... | @@ -168,7 +168,7 @@ fn entryPtr() void { |
| 168 | 168 | fooPtr(ptr); |
| 169 | 169 | } |
| 170 | 170 | |
| 171 | fn foo2(f: fn () anyerror!void) void { | |
| 171 | fn foo2(comptime f: fn () anyerror!void) void { | |
| 172 | 172 | const x = f(); |
| 173 | 173 | x catch { |
| 174 | 174 | @panic("fail"); |
test/behavior/eval.zig+22| ... | ... | @@ -1325,3 +1325,25 @@ test "value in if block is comptime known" { |
| 1325 | 1325 | }; |
| 1326 | 1326 | comptime try expect(std.mem.eql(u8, first, second)); |
| 1327 | 1327 | } |
| 1328 | ||
| 1329 | test "lazy sizeof is resolved in division" { | |
| 1330 | const A = struct { | |
| 1331 | a: u32, | |
| 1332 | }; | |
| 1333 | const a = 2; | |
| 1334 | try expect(@sizeOf(A) / a == 2); | |
| 1335 | try expect(@sizeOf(A) - a == 2); | |
| 1336 | } | |
| 1337 | ||
| 1338 | test "lazy value is resolved as slice operand" { | |
| 1339 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1340 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 1341 | ||
| 1342 | const A = struct { a: u32 }; | |
| 1343 | var a: [512]u64 = undefined; | |
| 1344 | ||
| 1345 | const ptr1 = a[0..@sizeOf(A)]; | |
| 1346 | const ptr2 = @ptrCast([*]u8, &a)[0..@sizeOf(A)]; | |
| 1347 | try expect(@ptrToInt(ptr1) == @ptrToInt(ptr2)); | |
| 1348 | try expect(ptr1.len == ptr2.len); | |
| 1349 | } |
test/behavior/fn.zig+22-1| ... | ... | @@ -137,7 +137,7 @@ test "implicit cast function unreachable return" { |
| 137 | 137 | wantsFnWithVoid(fnWithUnreachable); |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | fn wantsFnWithVoid(f: fn () void) void { | |
| 140 | fn wantsFnWithVoid(comptime f: fn () void) void { | |
| 141 | 141 | _ = f; |
| 142 | 142 | } |
| 143 | 143 | |
| ... | ... | @@ -422,3 +422,24 @@ test "import passed byref to function in return type" { |
| 422 | 422 | var list = S.get(); |
| 423 | 423 | try expect(list.items.len == 0); |
| 424 | 424 | } |
| 425 | ||
| 426 | test "implicit cast function to function ptr" { | |
| 427 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 428 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 429 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 430 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 431 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 432 | ||
| 433 | const S1 = struct { | |
| 434 | export fn someFunctionThatReturnsAValue() c_int { | |
| 435 | return 123; | |
| 436 | } | |
| 437 | }; | |
| 438 | var fnPtr1: *const fn () callconv(.C) c_int = S1.someFunctionThatReturnsAValue; | |
| 439 | try expect(fnPtr1() == 123); | |
| 440 | const S2 = struct { | |
| 441 | extern fn someFunctionThatReturnsAValue() c_int; | |
| 442 | }; | |
| 443 | var fnPtr2: *const fn () callconv(.C) c_int = S2.someFunctionThatReturnsAValue; | |
| 444 | try expect(fnPtr2() == 123); | |
| 445 | } |
test/behavior/optional.zig+7| ... | ... | @@ -405,3 +405,10 @@ test "optional of noreturn used with orelse" { |
| 405 | 405 | const val = NoReturn.testOrelse(); |
| 406 | 406 | try expect(val == 123); |
| 407 | 407 | } |
| 408 | ||
| 409 | test "orelse on C pointer" { | |
| 410 | // TODO https://github.com/ziglang/zig/issues/6597 | |
| 411 | const foo: [*c]const u8 = "hey"; | |
| 412 | const d = foo orelse @compileError("bad"); | |
| 413 | try expectEqual([*c]const u8, @TypeOf(d)); | |
| 414 | } |
test/behavior/packed-struct.zig+12| ... | ... | @@ -434,3 +434,15 @@ test "@ptrToInt on a packed struct field" { |
| 434 | 434 | }; |
| 435 | 435 | try expect(@ptrToInt(&S.p0.z) - @ptrToInt(&S.p0.x) == 2); |
| 436 | 436 | } |
| 437 | ||
| 438 | test "optional pointer in packed struct" { | |
| 439 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 440 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 441 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 442 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 443 | ||
| 444 | const T = packed struct { ptr: ?*const u8 }; | |
| 445 | var n: u8 = 0; | |
| 446 | const x = T{ .ptr = &n }; | |
| 447 | try expect(x.ptr.? == &n); | |
| 448 | } |
test/behavior/struct.zig+1-1| ... | ... | @@ -147,7 +147,7 @@ test "fn call of struct field" { |
| 147 | 147 | return 13; |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | fn callStructField(foo: Foo) i32 { | |
| 150 | fn callStructField(comptime foo: Foo) i32 { | |
| 151 | 151 | return foo.ptr(); |
| 152 | 152 | } |
| 153 | 153 | }; |
test/cases/compile_errors/bogus_method_call_on_slice.zig+8| ... | ... | @@ -3,9 +3,17 @@ fn f(m: []const u8) void { |
| 3 | 3 | m.copy(u8, self[0..], m); |
| 4 | 4 | } |
| 5 | 5 | export fn entry() usize { return @sizeOf(@TypeOf(&f)); } |
| 6 | pub export fn entry1() void { | |
| 7 | .{}.bar(); | |
| 8 | } | |
| 9 | pub export fn entry2() void { | |
| 10 | .{ .foo = 1 }.bar(); | |
| 11 | } | |
| 6 | 12 | |
| 7 | 13 | // error |
| 8 | 14 | // backend=stage2 |
| 9 | 15 | // target=native |
| 10 | 16 | // |
| 17 | // :7:8: error: no field or member function named 'bar' in '@TypeOf(.{})' | |
| 18 | // :10:18: error: no field or member function named 'bar' in 'struct{comptime foo: comptime_int = 1}' | |
| 11 | 19 | // :3:6: error: no field or member function named 'copy' in '[]const u8' |
test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | fn f(_: anytype) void {} | |
| 2 | fn g(h: *const fn (anytype) void) void { | |
| 3 | h({}); | |
| 4 | } | |
| 5 | pub export fn entry() void { | |
| 6 | g(f); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn comptimeMod(num: anytype, denom: comptime_int) void { | |
| 10 | _ = num; | |
| 11 | _ = denom; | |
| 12 | } | |
| 13 | ||
| 14 | pub export fn entry1() void { | |
| 15 | _ = comptimeMod(1, 2); | |
| 16 | } | |
| 17 | ||
| 18 | // error | |
| 19 | // backend=stage2 | |
| 20 | // target=native | |
| 21 | // | |
| 22 | // :2:6: error: parameter of type '*const fn(anytype) void' must be declared comptime | |
| 23 | // :9:34: error: parameter of type 'comptime_int' must be declared comptime |
test/compile_errors.zig+18-1| ... | ... | @@ -184,7 +184,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | 186 | { |
| 187 | const case = ctx.obj("argument causes error ", .{}); | |
| 187 | const case = ctx.obj("argument causes error", .{}); | |
| 188 | 188 | case.backend = .stage2; |
| 189 | 189 | |
| 190 | 190 | case.addSourceFile("b.zig", |
| ... | ... | @@ -208,6 +208,23 @@ pub fn addCases(ctx: *TestContext) !void { |
| 208 | 208 | }); |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | { | |
| 212 | const case = ctx.obj("astgen failure in file struct", .{}); | |
| 213 | case.backend = .stage2; | |
| 214 | ||
| 215 | case.addSourceFile("b.zig", | |
| 216 | \\bad | |
| 217 | ); | |
| 218 | ||
| 219 | case.addError( | |
| 220 | \\pub export fn entry() void { | |
| 221 | \\ _ = (@sizeOf(@import("b.zig"))); | |
| 222 | \\} | |
| 223 | , &[_][]const u8{ | |
| 224 | ":1:1: error: struct field missing type", | |
| 225 | }); | |
| 226 | } | |
| 227 | ||
| 211 | 228 | // TODO test this in stage2, but we won't even try in stage1 |
| 212 | 229 | //ctx.objErrStage1("inline fn calls itself indirectly", |
| 213 | 230 | // \\export fn foo() void { |