| 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,8 +5024,8 @@ fn shiftLeftOne(a: u32) callconv(.Inline) u32 { |
| 5024 | // Another file can use @import and call sub2 | 5024 | // Another file can use @import and call sub2 |
| 5025 | pub fn sub2(a: i8, b: i8) i8 { return a - b; } | 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. | 5027 | // Function pointers are prefixed with `*const `. |
| 5028 | const call2_op = fn (a: i8, b: i8) i8; | 5028 | const call2_op = *const fn (a: i8, b: i8) i8; |
| 5029 | fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 { | 5029 | fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 { |
| 5030 | return fn_call(op1, op2); | 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,7 +42,7 @@ pub fn isSep(byte: u8) bool { |
| 42 | 42 | ||
| 43 | /// This is different from mem.join in that the separator will not be repeated if | 43 | /// This is different from mem.join in that the separator will not be repeated if |
| 44 | /// it is found at the end or beginning of a pair of consecutive paths. | 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 | if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{}; | 46 | if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{}; |
| 47 | 47 | ||
| 48 | // Find first non-empty path index. | 48 | // Find first non-empty path index. |
lib/std/math.zig+1-1| ... | @@ -1548,7 +1548,7 @@ test "boolMask" { | ... | @@ -1548,7 +1548,7 @@ test "boolMask" { |
| 1548 | } | 1548 | } |
| 1549 | 1549 | ||
| 1550 | /// Return the mod of `num` with the smallest integer type | 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 | return @intCast(IntFittingRange(0, denom - 1), @mod(num, denom)); | 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,7 +8,7 @@ inline fn mantissaOne(comptime T: type) comptime_int { |
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | /// Creates floating point type T from an unbiased exponent and raw mantissa. | 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 | const TBits = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); | 12 | const TBits = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); |
| 13 | const biased_exponent = @as(TBits, exponent + floatExponentMax(T)); | 13 | const biased_exponent = @as(TBits, exponent + floatExponentMax(T)); |
| 14 | return @bitCast(T, (biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa)); | 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,7 +349,7 @@ test "shuffleVectorIndex" { |
| 349 | 349 | ||
| 350 | /// Constructs a [*c] pointer with the const and volatile annotations | 350 | /// Constructs a [*c] pointer with the const and volatile annotations |
| 351 | /// from SelfType for pointing to a C flexible array of ElementType. | 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 | switch (@typeInfo(SelfType)) { | 353 | switch (@typeInfo(SelfType)) { |
| 354 | .Pointer => |ptr| { | 354 | .Pointer => |ptr| { |
| 355 | return @Type(.{ .Pointer = .{ | 355 | return @Type(.{ .Pointer = .{ |
lib/std/zig/parse.zig+1-1| ... | @@ -3670,7 +3670,7 @@ const Parser = struct { | ... | @@ -3670,7 +3670,7 @@ const Parser = struct { |
| 3670 | } | 3670 | } |
| 3671 | 3671 | ||
| 3672 | /// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)? | 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 | const if_token = p.eatToken(.keyword_if) orelse return null_node; | 3674 | const if_token = p.eatToken(.keyword_if) orelse return null_node; |
| 3675 | _ = try p.expectToken(.l_paren); | 3675 | _ = try p.expectToken(.l_paren); |
| 3676 | const condition = try p.expectExpr(); | 3676 | const condition = try p.expectExpr(); |
src/Module.zig+4-4| ... | @@ -6072,17 +6072,17 @@ pub fn paramSrc( | ... | @@ -6072,17 +6072,17 @@ pub fn paramSrc( |
| 6072 | else => unreachable, | 6072 | else => unreachable, |
| 6073 | }; | 6073 | }; |
| 6074 | var it = full.iterate(tree); | 6074 | var it = full.iterate(tree); |
| 6075 | while (true) { | 6075 | var i: usize = 0; |
| 6076 | if (it.param_i == param_i) { | 6076 | while (it.next()) |param| : (i += 1) { |
| 6077 | const param = it.next().?; | 6077 | if (i == param_i) { |
| 6078 | if (param.anytype_ellipsis3) |some| { | 6078 | if (param.anytype_ellipsis3) |some| { |
| 6079 | const main_token = tree.nodes.items(.main_token)[decl.src_node]; | 6079 | const main_token = tree.nodes.items(.main_token)[decl.src_node]; |
| 6080 | return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) }; | 6080 | return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) }; |
| 6081 | } | 6081 | } |
| 6082 | return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) }; | 6082 | return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) }; |
| 6083 | } | 6083 | } |
| 6084 | _ = it.next(); | ||
| 6085 | } | 6084 | } |
| 6085 | unreachable; | ||
| 6086 | } | 6086 | } |
| 6087 | 6087 | ||
| 6088 | pub fn argSrc( | 6088 | pub fn argSrc( |
src/Sema.zig+46-17| ... | @@ -76,6 +76,8 @@ types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{}, | ... | @@ -76,6 +76,8 @@ types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{}, |
| 76 | post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{}, | 76 | post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{}, |
| 77 | /// Populated with the last compile error created. | 77 | /// Populated with the last compile error created. |
| 78 | err: ?*Module.ErrorMsg = null, | 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 | const std = @import("std"); | 82 | const std = @import("std"); |
| 81 | const math = std.math; | 83 | const math = std.math; |
| ... | @@ -1696,7 +1698,10 @@ fn resolveMaybeUndefValIntable( | ... | @@ -1696,7 +1698,10 @@ fn resolveMaybeUndefValIntable( |
| 1696 | .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr, | 1698 | .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr, |
| 1697 | .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr, | 1699 | .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr, |
| 1698 | .generic_poison => return error.GenericPoison, | 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,6 +6500,7 @@ fn instantiateGenericCall( |
| 6495 | .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len), | 6500 | .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len), |
| 6496 | .comptime_args_fn_inst = module_fn.zir_body_inst, | 6501 | .comptime_args_fn_inst = module_fn.zir_body_inst, |
| 6497 | .preallocated_new_func = new_module_func, | 6502 | .preallocated_new_func = new_module_func, |
| 6503 | .is_generic_instantiation = true, | ||
| 6498 | }; | 6504 | }; |
| 6499 | defer child_sema.deinit(); | 6505 | defer child_sema.deinit(); |
| 6500 | 6506 | ||
| ... | @@ -7255,6 +7261,8 @@ fn zirOptionalPayload( | ... | @@ -7255,6 +7261,8 @@ fn zirOptionalPayload( |
| 7255 | if (operand_ty.ptrSize() != .C) { | 7261 | if (operand_ty.ptrSize() != .C) { |
| 7256 | return sema.failWithExpectedOptionalType(block, src, operand_ty); | 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 | const ptr_info = operand_ty.ptrInfo().data; | 7266 | const ptr_info = operand_ty.ptrInfo().data; |
| 7259 | break :t try Type.ptr(sema.arena, sema.mod, .{ | 7267 | break :t try Type.ptr(sema.arena, sema.mod, .{ |
| 7260 | .pointee_type = try ptr_info.pointee_type.copy(sema.arena), | 7268 | .pointee_type = try ptr_info.pointee_type.copy(sema.arena), |
| ... | @@ -7789,6 +7797,7 @@ fn funcCommon( | ... | @@ -7789,6 +7797,7 @@ fn funcCommon( |
| 7789 | &is_generic, | 7797 | &is_generic, |
| 7790 | is_extern, | 7798 | is_extern, |
| 7791 | cc_workaround, | 7799 | cc_workaround, |
| 7800 | has_body, | ||
| 7792 | ) catch |err| switch (err) { | 7801 | ) catch |err| switch (err) { |
| 7793 | error.NeededSourceLocation => { | 7802 | error.NeededSourceLocation => { |
| 7794 | const decl = sema.mod.declPtr(block.src_decl); | 7803 | const decl = sema.mod.declPtr(block.src_decl); |
| ... | @@ -7802,6 +7811,7 @@ fn funcCommon( | ... | @@ -7802,6 +7811,7 @@ fn funcCommon( |
| 7802 | &is_generic, | 7811 | &is_generic, |
| 7803 | is_extern, | 7812 | is_extern, |
| 7804 | cc_workaround, | 7813 | cc_workaround, |
| 7814 | has_body, | ||
| 7805 | ); | 7815 | ); |
| 7806 | return error.AnalysisFail; | 7816 | return error.AnalysisFail; |
| 7807 | }, | 7817 | }, |
| ... | @@ -8005,6 +8015,7 @@ fn analyzeParameter( | ... | @@ -8005,6 +8015,7 @@ fn analyzeParameter( |
| 8005 | is_generic: *bool, | 8015 | is_generic: *bool, |
| 8006 | is_extern: bool, | 8016 | is_extern: bool, |
| 8007 | cc: std.builtin.CallingConvention, | 8017 | cc: std.builtin.CallingConvention, |
| 8018 | has_body: bool, | ||
| 8008 | ) !void { | 8019 | ) !void { |
| 8009 | const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty); | 8020 | const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty); |
| 8010 | comptime_params[i] = param.is_comptime or requires_comptime; | 8021 | comptime_params[i] = param.is_comptime or requires_comptime; |
| ... | @@ -8053,9 +8064,9 @@ fn analyzeParameter( | ... | @@ -8053,9 +8064,9 @@ fn analyzeParameter( |
| 8053 | }; | 8064 | }; |
| 8054 | return sema.failWithOwnedErrorMsg(msg); | 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 | const msg = msg: { | 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 | param.ty.fmt(sema.mod), | 8070 | param.ty.fmt(sema.mod), |
| 8060 | }); | 8071 | }); |
| 8061 | errdefer msg.destroy(sema.gpa); | 8072 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -8153,7 +8164,7 @@ fn zirParam( | ... | @@ -8153,7 +8164,7 @@ fn zirParam( |
| 8153 | 8164 | ||
| 8154 | try block.params.append(sema.gpa, .{ | 8165 | try block.params.append(sema.gpa, .{ |
| 8155 | .ty = param_ty, | 8166 | .ty = param_ty, |
| 8156 | .is_comptime = is_comptime, | 8167 | .is_comptime = comptime_syntax, |
| 8157 | .name = param_name, | 8168 | .name = param_name, |
| 8158 | }); | 8169 | }); |
| 8159 | const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison)); | 8170 | const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison)); |
| ... | @@ -16318,7 +16329,7 @@ fn zirUnaryMath( | ... | @@ -16318,7 +16329,7 @@ fn zirUnaryMath( |
| 16318 | block: *Block, | 16329 | block: *Block, |
| 16319 | inst: Zir.Inst.Index, | 16330 | inst: Zir.Inst.Index, |
| 16320 | air_tag: Air.Inst.Tag, | 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 | ) CompileError!Air.Inst.Ref { | 16333 | ) CompileError!Air.Inst.Ref { |
| 16323 | const tracy = trace(@src()); | 16334 | const tracy = trace(@src()); |
| 16324 | defer tracy.end(); | 16335 | defer tracy.end(); |
| ... | @@ -17777,7 +17788,7 @@ fn zirBitCount( | ... | @@ -17777,7 +17788,7 @@ fn zirBitCount( |
| 17777 | block: *Block, | 17788 | block: *Block, |
| 17778 | inst: Zir.Inst.Index, | 17789 | inst: Zir.Inst.Index, |
| 17779 | air_tag: Air.Inst.Tag, | 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 | ) CompileError!Air.Inst.Ref { | 17792 | ) CompileError!Air.Inst.Ref { |
| 17782 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 17793 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 17783 | const src = inst_data.src(); | 17794 | const src = inst_data.src(); |
| ... | @@ -20554,8 +20565,8 @@ fn validatePackedType(ty: Type) bool { | ... | @@ -20554,8 +20565,8 @@ fn validatePackedType(ty: Type) bool { |
| 20554 | .AnyFrame, | 20565 | .AnyFrame, |
| 20555 | .Fn, | 20566 | .Fn, |
| 20556 | .Array, | 20567 | .Array, |
| 20557 | .Optional, | ||
| 20558 | => return false, | 20568 | => return false, |
| 20569 | .Optional => return ty.isPtrLikeOptional(), | ||
| 20559 | .Void, | 20570 | .Void, |
| 20560 | .Bool, | 20571 | .Bool, |
| 20561 | .Float, | 20572 | .Float, |
| ... | @@ -21383,14 +21394,30 @@ fn fieldCallBind( | ... | @@ -21383,14 +21394,30 @@ fn fieldCallBind( |
| 21383 | switch (concrete_ty.zigTypeTag()) { | 21394 | switch (concrete_ty.zigTypeTag()) { |
| 21384 | .Struct => { | 21395 | .Struct => { |
| 21385 | const struct_ty = try sema.resolveTypeFields(block, src, concrete_ty); | 21396 | const struct_ty = try sema.resolveTypeFields(block, src, concrete_ty); |
| 21386 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 21397 | if (struct_ty.castTag(.@"struct")) |struct_obj| { |
| 21387 | 21398 | const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse | |
| 21388 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse | 21399 | break :find_field; |
| 21389 | break :find_field; | 21400 | const field_index = @intCast(u32, field_index_usize); |
| 21390 | const field_index = @intCast(u32, field_index_usize); | 21401 | const field = struct_obj.data.fields.values()[field_index]; |
| 21391 | const field = struct_obj.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 | .Union => { | 21422 | .Union => { |
| 21396 | const union_ty = try sema.resolveTypeFields(block, src, concrete_ty); | 21423 | const union_ty = try sema.resolveTypeFields(block, src, concrete_ty); |
| ... | @@ -22553,7 +22580,7 @@ fn coerceExtra( | ... | @@ -22553,7 +22580,7 @@ fn coerceExtra( |
| 22553 | // Function body to function pointer. | 22580 | // Function body to function pointer. |
| 22554 | if (inst_ty.zigTypeTag() == .Fn) { | 22581 | if (inst_ty.zigTypeTag() == .Fn) { |
| 22555 | const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined); | 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 | const inst_as_ptr = try sema.analyzeDeclRef(fn_decl); | 22584 | const inst_as_ptr = try sema.analyzeDeclRef(fn_decl); |
| 22558 | return sema.coerce(block, dest_ty, inst_as_ptr, inst_src); | 22585 | return sema.coerce(block, dest_ty, inst_as_ptr, inst_src); |
| 22559 | } | 22586 | } |
| ... | @@ -27909,7 +27936,9 @@ fn resolveInferredErrorSetTy( | ... | @@ -27909,7 +27936,9 @@ fn resolveInferredErrorSetTy( |
| 27909 | fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void { | 27936 | fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void { |
| 27910 | const gpa = mod.gpa; | 27937 | const gpa = mod.gpa; |
| 27911 | const decl_index = struct_obj.owner_decl; | 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 | const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended; | 27942 | const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended; |
| 27914 | assert(extended.opcode == .struct_decl); | 27943 | assert(extended.opcode == .struct_decl); |
| 27915 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); | 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,7 +29518,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 29489 | => { | 29518 | => { |
| 29490 | const child_ty = ty.childType(); | 29519 | const child_ty = ty.childType(); |
| 29491 | if (child_ty.zigTypeTag() == .Fn) { | 29520 | if (child_ty.zigTypeTag() == .Fn) { |
| 29492 | return false; | 29521 | return child_ty.fnInfo().is_generic; |
| 29493 | } else { | 29522 | } else { |
| 29494 | return sema.typeRequiresComptime(block, src, child_ty); | 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,7 +3417,10 @@ pub const DeclGen = struct { |
| 3417 | }); | 3417 | }); |
| 3418 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); | 3418 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); |
| 3419 | const small_int_ty = dg.context.intType(ty_bit_size); | 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 | const shift_rhs = int_llvm_ty.constInt(running_bits, .False); | 3424 | const shift_rhs = int_llvm_ty.constInt(running_bits, .False); |
| 3422 | // If the field is as large as the entire packed struct, this | 3425 | // If the field is as large as the entire packed struct, this |
| 3423 | // zext would go from, e.g. i16 to i16. This is legal with | 3426 | // zext would go from, e.g. i16 to i16. This is legal with |
| ... | @@ -5343,7 +5346,7 @@ pub const FuncGen = struct { | ... | @@ -5343,7 +5346,7 @@ pub const FuncGen = struct { |
| 5343 | const same_size_int = self.context.intType(elem_bits); | 5346 | const same_size_int = self.context.intType(elem_bits); |
| 5344 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 5347 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 5345 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); | 5348 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 5346 | } else if (field_ty.zigTypeTag() == .Pointer) { | 5349 | } else if (field_ty.isPtrAtRuntime()) { |
| 5347 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); | 5350 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); |
| 5348 | const same_size_int = self.context.intType(elem_bits); | 5351 | const same_size_int = self.context.intType(elem_bits); |
| 5349 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 5352 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| ... | @@ -8408,7 +8411,7 @@ pub const FuncGen = struct { | ... | @@ -8408,7 +8411,7 @@ pub const FuncGen = struct { |
| 8408 | const non_int_val = try self.resolveInst(elem); | 8411 | const non_int_val = try self.resolveInst(elem); |
| 8409 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); | 8412 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); |
| 8410 | const small_int_ty = self.dg.context.intType(ty_bit_size); | 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 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") | 8415 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 8413 | else | 8416 | else |
| 8414 | self.builder.buildBitCast(non_int_val, small_int_ty, ""); | 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,7 +2394,7 @@ pub const Type = extern union { |
| 2394 | if (ignore_comptime_only) { | 2394 | if (ignore_comptime_only) { |
| 2395 | return true; | 2395 | return true; |
| 2396 | } else if (ty.childType().zigTypeTag() == .Fn) { | 2396 | } else if (ty.childType().zigTypeTag() == .Fn) { |
| 2397 | return true; | 2397 | return !ty.childType().fnInfo().is_generic; |
| 2398 | } else if (sema_kit) |sk| { | 2398 | } else if (sema_kit) |sk| { |
| 2399 | return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty)); | 2399 | return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty)); |
| 2400 | } else { | 2400 | } else { |
test/behavior/cast.zig+1-1| ... | @@ -1281,7 +1281,7 @@ test "*const [N]null u8 to ?[]const u8" { | ... | @@ -1281,7 +1281,7 @@ test "*const [N]null u8 to ?[]const u8" { |
| 1281 | test "cast between [*c]T and ?[*:0]T on fn parameter" { | 1281 | test "cast between [*c]T and ?[*:0]T on fn parameter" { |
| 1282 | const S = struct { | 1282 | const S = struct { |
| 1283 | const Handler = ?fn ([*c]const u8) callconv(.C) void; | 1283 | const Handler = ?fn ([*c]const u8) callconv(.C) void; |
| 1284 | fn addCallback(handler: Handler) void { | 1284 | fn addCallback(comptime handler: Handler) void { |
| 1285 | _ = handler; | 1285 | _ = handler; |
| 1286 | } | 1286 | } |
| 1287 | 1287 |
test/behavior/error.zig+1-1| ... | @@ -168,7 +168,7 @@ fn entryPtr() void { | ... | @@ -168,7 +168,7 @@ fn entryPtr() void { |
| 168 | fooPtr(ptr); | 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 | const x = f(); | 172 | const x = f(); |
| 173 | x catch { | 173 | x catch { |
| 174 | @panic("fail"); | 174 | @panic("fail"); |
test/behavior/eval.zig+22| ... | @@ -1325,3 +1325,25 @@ test "value in if block is comptime known" { | ... | @@ -1325,3 +1325,25 @@ test "value in if block is comptime known" { |
| 1325 | }; | 1325 | }; |
| 1326 | comptime try expect(std.mem.eql(u8, first, second)); | 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,7 +137,7 @@ test "implicit cast function unreachable return" { |
| 137 | wantsFnWithVoid(fnWithUnreachable); | 137 | wantsFnWithVoid(fnWithUnreachable); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | fn wantsFnWithVoid(f: fn () void) void { | 140 | fn wantsFnWithVoid(comptime f: fn () void) void { |
| 141 | _ = f; | 141 | _ = f; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| ... | @@ -422,3 +422,24 @@ test "import passed byref to function in return type" { | ... | @@ -422,3 +422,24 @@ test "import passed byref to function in return type" { |
| 422 | var list = S.get(); | 422 | var list = S.get(); |
| 423 | try expect(list.items.len == 0); | 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,3 +405,10 @@ test "optional of noreturn used with orelse" { |
| 405 | const val = NoReturn.testOrelse(); | 405 | const val = NoReturn.testOrelse(); |
| 406 | try expect(val == 123); | 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,3 +434,15 @@ test "@ptrToInt on a packed struct field" { |
| 434 | }; | 434 | }; |
| 435 | try expect(@ptrToInt(&S.p0.z) - @ptrToInt(&S.p0.x) == 2); | 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,7 +147,7 @@ test "fn call of struct field" { |
| 147 | return 13; | 147 | return 13; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | fn callStructField(foo: Foo) i32 { | 150 | fn callStructField(comptime foo: Foo) i32 { |
| 151 | return foo.ptr(); | 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,9 +3,17 @@ fn f(m: []const u8) void { |
| 3 | m.copy(u8, self[0..], m); | 3 | m.copy(u8, self[0..], m); |
| 4 | } | 4 | } |
| 5 | export fn entry() usize { return @sizeOf(@TypeOf(&f)); } | 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 | // error | 13 | // error |
| 8 | // backend=stage2 | 14 | // backend=stage2 |
| 9 | // target=native | 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 | // :3:6: error: no field or member function named 'copy' in '[]const u8' | 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,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 | case.backend = .stage2; | 188 | case.backend = .stage2; |
| 189 | 189 | ||
| 190 | case.addSourceFile("b.zig", | 190 | case.addSourceFile("b.zig", |
| ... | @@ -208,6 +208,23 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -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 | // TODO test this in stage2, but we won't even try in stage1 | 228 | // TODO test this in stage2, but we won't even try in stage1 |
| 212 | //ctx.objErrStage1("inline fn calls itself indirectly", | 229 | //ctx.objErrStage1("inline fn calls itself indirectly", |
| 213 | // \\export fn foo() void { | 230 | // \\export fn foo() void { |