authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-25 03:31:57-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-09-25 03:31:57-04:00
log6d7b0690a0e49819ffd92e330f0fd48a7abc0d16
treeda0e7fe7edb37c0367964c1b0d43d94eabeb9543
parentcae76d8293f6416ff698171c2ae10552fa014587
parentc4400e8aa58c9ba5e4cc51836a2cfa6c2e22bfcc
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12942 from Vexu/stage2-fixes

misc stage2 fixes

13 files changed, 277 insertions(+), 38 deletions(-)

src/AstGen.zig+32
......@@ -577,6 +577,12 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
577577 const node_datas = tree.nodes.items(.data);
578578 const node_tags = tree.nodes.items(.tag);
579579
580 const prev_anon_name_strategy = gz.anon_name_strategy;
581 defer gz.anon_name_strategy = prev_anon_name_strategy;
582 if (!nodeUsesAnonNameStrategy(tree, node)) {
583 gz.anon_name_strategy = .anon;
584 }
585
580586 switch (node_tags[node]) {
581587 .root => unreachable, // Top-level declaration.
582588 .@"usingnamespace" => unreachable, // Top-level declaration.
......@@ -9344,6 +9350,32 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
93449350 }
93459351}
93469352
9353/// Returns `true` if the node uses `gz.anon_name_strategy`.
9354fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
9355 const node_tags = tree.nodes.items(.tag);
9356 switch (node_tags[node]) {
9357 .container_decl,
9358 .container_decl_trailing,
9359 .container_decl_two,
9360 .container_decl_two_trailing,
9361 .container_decl_arg,
9362 .container_decl_arg_trailing,
9363 .tagged_union,
9364 .tagged_union_trailing,
9365 .tagged_union_two,
9366 .tagged_union_two_trailing,
9367 .tagged_union_enum_tag,
9368 .tagged_union_enum_tag_trailing,
9369 => return true,
9370 .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => {
9371 const builtin_token = tree.nodes.items(.main_token)[node];
9372 const builtin_name = tree.tokenSlice(builtin_token);
9373 return std.mem.eql(u8, builtin_name, "@Type");
9374 },
9375 else => return false,
9376 }
9377}
9378
93479379/// Applies `rl` semantics to `result`. Expressions which do not do their own handling of
93489380/// result locations must call this function on their result.
93499381/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
src/Sema.zig+70-36
......@@ -8180,7 +8180,7 @@ fn analyzeParameter(
81808180 if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(cc)) {
81818181 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
81828182 }
8183 if (this_generic and !Type.fnCallingConventionAllowsZigTypes(cc)) {
8183 if (this_generic and !sema.no_partial_func_ty and !Type.fnCallingConventionAllowsZigTypes(cc)) {
81848184 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
81858185 }
81868186 if (!param.ty.isValidParamType()) {
......@@ -8196,7 +8196,7 @@ fn analyzeParameter(
81968196 };
81978197 return sema.failWithOwnedErrorMsg(msg);
81988198 }
8199 if (!Type.fnCallingConventionAllowsZigTypes(cc) and !try sema.validateExternType(block, param_src, param.ty, .param_ty)) {
8199 if (!this_generic and !Type.fnCallingConventionAllowsZigTypes(cc) and !try sema.validateExternType(block, param_src, param.ty, .param_ty)) {
82008200 const msg = msg: {
82018201 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
82028202 param.ty.fmt(sema.mod), @tagName(cc),
......@@ -8277,8 +8277,21 @@ fn zirParam(
82778277 else => |e| return e,
82788278 }
82798279 };
8280 const is_comptime = comptime_syntax or
8281 try sema.typeRequiresComptime(param_ty);
8280 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {
8281 error.GenericPoison => {
8282 // The type is not available until the generic instantiation.
8283 // We result the param instruction with a poison value and
8284 // insert an anytype parameter.
8285 try block.params.append(sema.gpa, .{
8286 .ty = Type.initTag(.generic_poison),
8287 .is_comptime = comptime_syntax,
8288 .name = param_name,
8289 });
8290 try sema.inst_map.putNoClobber(sema.gpa, inst, .generic_poison);
8291 return;
8292 },
8293 else => |e| return e,
8294 } or comptime_syntax;
82828295 if (sema.inst_map.get(inst)) |arg| {
82838296 if (is_comptime) {
82848297 // We have a comptime value for this parameter so it should be elided from the
......@@ -15966,8 +15979,8 @@ fn zirStructInit(
1596615979 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
1596715980 const first_field_type_data = zir_datas[first_item.field_type].pl_node;
1596815981 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;
15969 const unresolved_struct_type = try sema.resolveType(block, src, first_field_type_extra.container_type);
15970 const resolved_ty = try sema.resolveTypeFields(block, src, unresolved_struct_type);
15982 const resolved_ty = try sema.resolveType(block, src, first_field_type_extra.container_type);
15983 try sema.resolveTypeLayout(block, src, resolved_ty);
1597115984
1597215985 if (resolved_ty.zigTypeTag() == .Struct) {
1597315986 // This logic must be synchronized with that in `zirStructInitEmpty`.
......@@ -17017,14 +17030,14 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1701717030 const payload_val = union_val.val.optionalValue() orelse
1701817031 return sema.addType(Type.initTag(.anyerror));
1701917032 const slice_val = payload_val.castTag(.slice).?.data;
17020 const decl_index = slice_val.ptr.pointerDecl().?;
17021 try sema.ensureDeclAnalyzed(decl_index);
17022 const decl = mod.declPtr(decl_index);
17023 const array_val: []Value = if (decl.val.castTag(.aggregate)) |some| some.data else &.{};
1702417033
17034 const len = try sema.usizeCast(block, src, slice_val.len.toUnsignedInt(mod.getTarget()));
1702517035 var names: Module.ErrorSet.NameMap = .{};
17026 try names.ensureUnusedCapacity(sema.arena, array_val.len);
17027 for (array_val) |elem_val| {
17036 try names.ensureUnusedCapacity(sema.arena, len);
17037 var i: usize = 0;
17038 while (i < len) : (i += 1) {
17039 var buf: Value.ElemValueBuffer = undefined;
17040 const elem_val = slice_val.ptr.elemValueBuffer(mod, i, &buf);
1702817041 const struct_val = elem_val.castTag(.aggregate).?.data;
1702917042 // TODO use reflection instead of magic numbers here
1703017043 // error_set: type,
......@@ -17416,14 +17429,14 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1741617429 var buf: Value.ToTypeBuffer = undefined;
1741717430
1741817431 const args_slice_val = args_val.castTag(.slice).?.data;
17419 const args_decl_index = args_slice_val.ptr.pointerDecl().?;
17420 try sema.ensureDeclAnalyzed(args_decl_index);
17421 const args_decl = mod.declPtr(args_decl_index);
17422 const args: []Value = if (args_decl.val.castTag(.aggregate)) |some| some.data else &.{};
17423 var param_types = try sema.arena.alloc(Type, args.len);
17424 var comptime_params = try sema.arena.alloc(bool, args.len);
17432 const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod.getTarget()));
17433 var param_types = try sema.arena.alloc(Type, args_len);
17434 var comptime_params = try sema.arena.alloc(bool, args_len);
1742517435 var noalias_bits: u32 = 0;
17426 for (args) |arg, i| {
17436 var i: usize = 0;
17437 while (i < args_len) : (i += 1) {
17438 var arg_buf: Value.ElemValueBuffer = undefined;
17439 const arg = args_slice_val.ptr.elemValueBuffer(mod, i, &arg_buf);
1742717440 const arg_val = arg.castTag(.aggregate).?.data;
1742817441 // TODO use reflection instead of magic numbers here
1742917442 // is_generic: bool,
......@@ -20841,9 +20854,9 @@ fn validateExternType(
2084120854 .Opaque,
2084220855 .Bool,
2084320856 .Float,
20844 .Pointer,
2084520857 .AnyFrame,
2084620858 => return true,
20859 .Pointer => return !ty.isSlice(),
2084720860 .Int => switch (ty.intInfo(sema.mod.getTarget()).bits) {
2084820861 8, 16, 32, 64, 128 => return true,
2084920862 else => return false,
......@@ -20886,7 +20899,6 @@ fn explainWhyTypeIsNotExtern(
2088620899 .Opaque,
2088720900 .Bool,
2088820901 .Float,
20889 .Pointer,
2089020902 .AnyFrame,
2089120903 => return,
2089220904
......@@ -20902,6 +20914,7 @@ fn explainWhyTypeIsNotExtern(
2090220914 .Frame,
2090320915 => return,
2090420916
20917 .Pointer => try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{}),
2090520918 .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}),
2090620919 .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}),
2090720920 .Int => if (ty.intInfo(sema.mod.getTarget()).bits > 128) {
......@@ -20960,11 +20973,11 @@ fn validatePackedType(ty: Type) bool {
2096020973 .Void,
2096120974 .Bool,
2096220975 .Float,
20963 .Pointer,
2096420976 .Int,
2096520977 .Vector,
2096620978 .Enum,
2096720979 => return true,
20980 .Pointer => return !ty.isSlice(),
2096820981 .Struct, .Union => return ty.containerLayout() == .Packed,
2096920982 }
2097020983}
......@@ -20980,7 +20993,6 @@ fn explainWhyTypeIsNotPacked(
2098020993 .Void,
2098120994 .Bool,
2098220995 .Float,
20983 .Pointer,
2098420996 .Int,
2098520997 .Vector,
2098620998 .Enum,
......@@ -21001,6 +21013,7 @@ fn explainWhyTypeIsNotPacked(
2100121013 .Optional,
2100221014 .Array,
2100321015 => try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}),
21016 .Pointer => try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{}),
2100421017 .Fn => {
2100521018 try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{});
2100621019 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
......@@ -22027,6 +22040,7 @@ fn structFieldPtrByIndex(
2202722040 var ptr_ty_data: Type.Payload.Pointer.Data = .{
2202822041 .pointee_type = field.ty,
2202922042 .mutable = struct_ptr_ty_info.mutable,
22043 .@"volatile" = struct_ptr_ty_info.@"volatile",
2203022044 .@"addrspace" = struct_ptr_ty_info.@"addrspace",
2203122045 };
2203222046
......@@ -22246,6 +22260,7 @@ fn unionFieldPtr(
2224622260 const ptr_field_ty = try Type.ptr(arena, sema.mod, .{
2224722261 .pointee_type = field.ty,
2224822262 .mutable = union_ptr_ty.ptrIsMutable(),
22263 .@"volatile" = union_ptr_ty.isVolatilePtr(),
2224922264 .@"addrspace" = union_ptr_ty.ptrAddressSpace(),
2225022265 });
2225122266 const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name).?);
......@@ -22568,6 +22583,7 @@ fn tupleFieldPtr(
2256822583 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{
2256922584 .pointee_type = field_ty,
2257022585 .mutable = tuple_ptr_ty.ptrIsMutable(),
22586 .@"volatile" = tuple_ptr_ty.isVolatilePtr(),
2257122587 .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(),
2257222588 });
2257322589
......@@ -23011,9 +23027,37 @@ fn coerceExtra(
2301123027 const dest_is_mut = dest_info.mutable;
2301223028
2301323029 const dst_elem_type = dest_info.pointee_type;
23014 switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src)) {
23030 const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src);
23031 switch (elem_res) {
2301523032 .ok => {},
23016 else => break :src_array_ptr,
23033 else => {
23034 in_memory_result = .{ .ptr_child = .{
23035 .child = try elem_res.dupe(sema.arena),
23036 .actual = array_elem_type,
23037 .wanted = dst_elem_type,
23038 } };
23039 break :src_array_ptr;
23040 },
23041 }
23042
23043 if (dest_info.sentinel) |dest_sent| {
23044 if (array_ty.sentinel()) |inst_sent| {
23045 if (!dest_sent.eql(inst_sent, dst_elem_type, sema.mod)) {
23046 in_memory_result = .{ .ptr_sentinel = .{
23047 .actual = inst_sent,
23048 .wanted = dest_sent,
23049 .ty = dst_elem_type,
23050 } };
23051 break :src_array_ptr;
23052 }
23053 } else {
23054 in_memory_result = .{ .ptr_sentinel = .{
23055 .actual = Value.initTag(.unreachable_value),
23056 .wanted = dest_sent,
23057 .ty = dst_elem_type,
23058 } };
23059 break :src_array_ptr;
23060 }
2301723061 }
2301823062
2301923063 switch (dest_info.size) {
......@@ -23027,17 +23071,7 @@ fn coerceExtra(
2302723071 },
2302823072 .Many => {
2302923073 // *[N]T to [*]T
23030 // *[N:s]T to [*:s]T
23031 // *[N:s]T to [*]T
23032 if (dest_info.sentinel) |dst_sentinel| {
23033 if (array_ty.sentinel()) |src_sentinel| {
23034 if (src_sentinel.eql(dst_sentinel, dst_elem_type, sema.mod)) {
23035 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
23036 }
23037 }
23038 } else {
23039 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
23040 }
23074 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2304123075 },
2304223076 .One => {},
2304323077 }
src/codegen/llvm.zig+6-2
......@@ -5972,7 +5972,9 @@ pub const FuncGen = struct {
59725972 }
59735973
59745974 if (!std.mem.eql(u8, name, "_")) {
5975 name_map.putAssumeCapacityNoClobber(name, total_i);
5975 const gop = name_map.getOrPutAssumeCapacity(name);
5976 if (gop.found_existing) return self.todo("duplicate asm output name '{s}'", .{name});
5977 gop.value_ptr.* = total_i;
59765978 }
59775979 total_i += 1;
59785980 }
......@@ -6028,7 +6030,9 @@ pub const FuncGen = struct {
60286030 }
60296031
60306032 if (!std.mem.eql(u8, name, "_")) {
6031 name_map.putAssumeCapacityNoClobber(name, total_i);
6033 const gop = name_map.getOrPutAssumeCapacity(name);
6034 if (gop.found_existing) return self.todo("duplicate asm input name '{s}'", .{name});
6035 gop.value_ptr.* = total_i;
60326036 }
60336037
60346038 // In the case of indirect inputs, LLVM requires the callsite to have
test/behavior.zig+4
......@@ -93,6 +93,10 @@ test {
9393 _ = @import("behavior/bugs/12794.zig");
9494 _ = @import("behavior/bugs/12801-1.zig");
9595 _ = @import("behavior/bugs/12801-2.zig");
96 _ = @import("behavior/bugs/12885.zig");
97 _ = @import("behavior/bugs/12911.zig");
98 _ = @import("behavior/bugs/12928.zig");
99 _ = @import("behavior/bugs/12945.zig");
96100 _ = @import("behavior/byteswap.zig");
97101 _ = @import("behavior/byval_arg_var.zig");
98102 _ = @import("behavior/call.zig");
test/behavior/bugs/12885.zig created+36
......@@ -0,0 +1,36 @@
1const std = @import("std");
2const builtin = std.builtin;
3const expect = std.testing.expect;
4
5const info = .{
6 .args = [_]builtin.Type.Error{
7 .{ .name = "bar" },
8 },
9};
10const Foo = @Type(.{
11 .ErrorSet = &info.args,
12});
13test "ErrorSet comptime_field_ptr" {
14 if (@import("builtin").zig_backend == .stage1) return error.SkipZigTest;
15
16 try expect(Foo == error{bar});
17}
18
19const fn_info = .{
20 .args = [_]builtin.Type.Fn.Param{
21 .{ .is_generic = false, .is_noalias = false, .arg_type = u8 },
22 },
23};
24const Bar = @Type(.{
25 .Fn = .{
26 .calling_convention = .Unspecified,
27 .alignment = 0,
28 .is_generic = false,
29 .is_var_args = false,
30 .return_type = void,
31 .args = &fn_info.args,
32 },
33});
34test "fn comptime_field_ptr" {
35 try expect(@typeInfo(Bar) == .Fn);
36}
test/behavior/bugs/12911.zig created+11
......@@ -0,0 +1,11 @@
1const builtin = @import("builtin");
2
3const Item = struct { field: u8 };
4const Thing = struct {
5 array: [1]Item,
6};
7test {
8 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
9
10 _ = Thing{ .array = undefined };
11}
test/behavior/bugs/12928.zig created+26
......@@ -0,0 +1,26 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const A = extern struct {
4 value: *volatile B,
5};
6const B = extern struct {
7 a: u32,
8 b: i32,
9};
10test {
11 var a: *A = undefined;
12 try expect(@TypeOf(&a.value.a) == *volatile u32);
13 try expect(@TypeOf(&a.value.b) == *volatile i32);
14}
15const C = extern struct {
16 value: *volatile D,
17};
18const D = extern union {
19 a: u32,
20 b: i32,
21};
22test {
23 var c: *C = undefined;
24 try expect(@TypeOf(&c.value.a) == *volatile u32);
25 try expect(@TypeOf(&c.value.b) == *volatile i32);
26}
test/behavior/bugs/12945.zig created+13
......@@ -0,0 +1,13 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4fn A(
5 comptime T: type,
6 comptime destroycb: ?*const fn (?*T) callconv(.C) void,
7) !void {
8 try expect(destroycb == null);
9}
10
11test {
12 try A(u32, null);
13}
test/behavior/generics.zig+13
......@@ -369,3 +369,16 @@ test "extern function used as generic parameter" {
369369 };
370370 try expect(S.baz(S.foo) != S.baz(S.bar));
371371}
372
373test "generic struct as parameter type" {
374 const S = struct {
375 fn doTheTest(comptime Int: type, thing: struct { int: Int }) !void {
376 try expect(thing.int == 123);
377 }
378 fn doTheTest2(comptime Int: type, comptime thing: struct { int: Int }) !void {
379 try expect(thing.int == 456);
380 }
381 };
382 try S.doTheTest(u32, .{ .int = 123 });
383 try S.doTheTest2(i32, .{ .int = 456 });
384}
test/behavior/typename.zig+25
......@@ -246,3 +246,28 @@ test "comptime parameters not converted to anytype in function type" {
246246 const T = fn (fn (type) void, void) void;
247247 try expectEqualStrings("fn(comptime fn(comptime type) void, void) void", @typeName(T));
248248}
249
250test "anon name strategy used in sub expression" {
251 if (builtin.zig_backend == .stage1) {
252 // stage1 uses line/column for the names but we're moving away from that for
253 // incremental compilation purposes.
254 return error.SkipZigTest;
255 }
256
257 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
258 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
261
262 const S = struct {
263 fn getTheName() []const u8 {
264 return struct {
265 const name = @typeName(@This());
266 }.name;
267 }
268 };
269 try expectEqualStringsIgnoreDigits(
270 "behavior.typename.test.anon name strategy used in sub expression.S.getTheName__struct_0",
271 S.getTheName(),
272 );
273}
test/cases/compile_errors/implicit_array_ptr_cast_sentinel_mismatch.zig created+23
......@@ -0,0 +1,23 @@
1fn foo() [:0xff]const u8 {
2 return "bark";
3}
4fn bar() [:0]const u16 {
5 return "bark";
6}
7pub export fn entry() void {
8 _ = foo();
9}
10pub export fn entry1() void {
11 _ = bar();
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :2:12: error: expected type '[:255]const u8', found '*const [4:0]u8'
19// :2:12: note: pointer sentinel '0' cannot cast into pointer sentinel '255'
20// :1:10: note: function return type declared here
21// :5:12: error: expected type '[:0]const u16', found '*const [4:0]u8'
22// :5:12: note: pointer type child 'u8' cannot cast into pointer type child 'u16'
23// :4:10: note: function return type declared here
test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig+7
......@@ -60,6 +60,11 @@ const U = extern union {
6060 A: i32,
6161 B: u32,
6262};
63export fn entry12() void {
64 _ = @sizeOf(packed struct {
65 x: packed struct { a: []u8 },
66 });
67}
6368
6469// error
6570// backend=llvm
......@@ -82,3 +87,5 @@ const U = extern union {
8287// :38:9: error: packed structs cannot contain fields of type 'fn() void'
8388// :38:9: note: type has no guaranteed in-memory representation
8489// :38:9: note: use '*const ' to make a function pointer type
90// :65:28: error: packed structs cannot contain fields of type '[]u8'
91// :65:28: note: slices have no guaranteed in-memory representation
test/cases/compile_errors/slice_used_as_extern_fn_param.zig created+11
......@@ -0,0 +1,11 @@
1extern fn Text(str: []const u8, num: i32) callconv(.C) void;
2export fn entry() void {
3 _ = Text;
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :1:16: error: parameter of type '[]const u8' not allowed in function with calling convention 'C'
11// :1:16: note: slices have no guaranteed in-memory representation