From 409cf4aeb826d8f7c35f0aa10bb0a8fe45188555 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 29 Sep 2022 15:04:07 +0300 Subject: [PATCH 1/4] Sema: use correct ptr ty to check for attributes of slice field ptr Closes #12870 Closes #13006 --- src/Sema.zig | 12 ++++++++---- test/behavior/slice.zig | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 5e6513251047fa918af0540299c64a001e4cdb12..7ad7491ea1c51d8a038d0adf9f919b851badf581 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -21664,14 +21664,17 @@ fn fieldPtr( else object_ptr; + const attr_ptr_ty = if (is_pointer_to) object_ty else object_ptr_ty; + if (mem.eql(u8, field_name, "ptr")) { const buf = try sema.arena.create(Type.SlicePtrFieldTypeBuffer); const slice_ptr_ty = inner_ty.slicePtrFieldType(buf); const result_ty = try Type.ptr(sema.arena, sema.mod, .{ .pointee_type = slice_ptr_ty, - .mutable = object_ptr_ty.ptrIsMutable(), - .@"addrspace" = object_ptr_ty.ptrAddressSpace(), + .mutable = attr_ptr_ty.ptrIsMutable(), + .@"volatile" = attr_ptr_ty.isVolatilePtr(), + .@"addrspace" = attr_ptr_ty.ptrAddressSpace(), }); if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| { @@ -21690,8 +21693,9 @@ fn fieldPtr( } else if (mem.eql(u8, field_name, "len")) { const result_ty = try Type.ptr(sema.arena, sema.mod, .{ .pointee_type = Type.usize, - .mutable = object_ptr_ty.ptrIsMutable(), - .@"addrspace" = object_ptr_ty.ptrAddressSpace(), + .mutable = attr_ptr_ty.ptrIsMutable(), + .@"volatile" = attr_ptr_ty.isVolatilePtr(), + .@"addrspace" = attr_ptr_ty.ptrAddressSpace(), }); if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| { diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index e5cb8ea4083ade0f5ab14fa3d6dae7a3ed34cc02..5aeb6a3414ad8a1161937b10bdcfb8688fc8f556 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -684,3 +684,31 @@ test "slice len modification at comptime" { try expect(items[1] == 1); } } + +test "slice field ptr const" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + + const const_slice: []const u8 = "string"; + + const const_ptr_const_slice = &const_slice; + try expectEqual(*const []const u8, @TypeOf(&const_ptr_const_slice.*)); + try expectEqual(*const [*]const u8, @TypeOf(&const_ptr_const_slice.ptr)); + + var var_ptr_const_slice = &const_slice; + try expectEqual(*const []const u8, @TypeOf(&var_ptr_const_slice.*)); + try expectEqual(*const [*]const u8, @TypeOf(&var_ptr_const_slice.ptr)); +} + +test "slice field ptr var" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + + var var_slice: []const u8 = "string"; + + var var_ptr_var_slice = &var_slice; + try expectEqual(*[]const u8, @TypeOf(&var_ptr_var_slice.*)); + try expectEqual(*[*]const u8, @TypeOf(&var_ptr_var_slice.ptr)); + + const const_ptr_var_slice = &var_slice; + try expectEqual(*[]const u8, @TypeOf(&const_ptr_var_slice.*)); + try expectEqual(*[*]const u8, @TypeOf(&const_ptr_var_slice.ptr)); +} -- 2.54.0 From b3c6d774d292e6e4ddf4cd54455c4ef3c6386d66 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 29 Sep 2022 17:45:27 +0300 Subject: [PATCH 2/4] stage2: improve error message for missing member in file root struct * the root struct decl name is fully qualified this prevents error messages containing 'main.main' * avoid declared here note when file struct is missing a member It always points at the start of the file which might contain another container misleading the user. --- src/Module.zig | 1 + src/Sema.zig | 5 +++++ test/cases/aarch64-macos/hello_world_with_updates.0.zig | 3 +-- test/cases/compile_errors/bogus_compile_var.zig | 3 +-- ...032_compile_diagnostic_string_for_top_level_decl_type.zig | 2 +- test/cases/x86_64-linux/hello_world_with_updates.0.zig | 3 +-- test/cases/x86_64-macos/hello_world_with_updates.0.zig | 3 +-- test/cases/x86_64-windows/hello_world_with_updates.0.zig | 3 +-- 8 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Module.zig b/src/Module.zig index e756cc3dfd29af9a42ab706e20035b0d12606c8e..6056c385e398c45e71cd64c62554e6602b1902fa 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -4435,6 +4435,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive. new_decl.analysis = .in_progress; new_decl.generation = mod.generation; + new_decl.name_fully_qualified = true; if (file.status == .success_zir) { assert(file.zir_loaded); diff --git a/src/Sema.zig b/src/Sema.zig index 7ad7491ea1c51d8a038d0adf9f919b851badf581..aed09d6201e5cd19f1c96b8638b48de9d68a27bb 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4353,6 +4353,11 @@ fn failWithBadMemberAccess( .Enum => "enum", else => unreachable, }; + if (sema.mod.declIsRoot(agg_ty.getOwnerDecl())) { + return sema.fail(block, field_src, "root struct of file '{}' has no member named '{s}'", .{ + agg_ty.fmt(sema.mod), field_name, + }); + } const msg = msg: { const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{s}'", .{ kw_name, agg_ty.fmt(sema.mod), field_name, diff --git a/test/cases/aarch64-macos/hello_world_with_updates.0.zig b/test/cases/aarch64-macos/hello_world_with_updates.0.zig index 3c7a4941800ce191e3e6e1b7079768c38e6f54f8..9f516ff1390f02aafc6203c8625793f8e58acdaf 100644 --- a/test/cases/aarch64-macos/hello_world_with_updates.0.zig +++ b/test/cases/aarch64-macos/hello_world_with_updates.0.zig @@ -2,5 +2,4 @@ // output_mode=Exe // target=aarch64-macos // -// :109:9: error: struct 'tmp.tmp' has no member named 'main' -// :7:1: note: struct declared here +// :109:9: error: root struct of file 'tmp' has no member named 'main' diff --git a/test/cases/compile_errors/bogus_compile_var.zig b/test/cases/compile_errors/bogus_compile_var.zig index b675fd941cf34031022cd6902569423032b68e53..be222e53934994ee4aee63211b33dc898c8d7183 100644 --- a/test/cases/compile_errors/bogus_compile_var.zig +++ b/test/cases/compile_errors/bogus_compile_var.zig @@ -5,5 +5,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(x)); } // backend=stage2 // target=native // -// :1:29: error: struct 'builtin.builtin' has no member named 'bogus' -// :1:1: note: struct declared here +// :1:29: error: root struct of file 'builtin' has no member named 'bogus' diff --git a/test/cases/compile_errors/issue_2032_compile_diagnostic_string_for_top_level_decl_type.zig b/test/cases/compile_errors/issue_2032_compile_diagnostic_string_for_top_level_decl_type.zig index 9ae320650ae826178811fb614b7d61292e374474..d78891bb2b86763228a2802f649b23eb45011b56 100644 --- a/test/cases/compile_errors/issue_2032_compile_diagnostic_string_for_top_level_decl_type.zig +++ b/test/cases/compile_errors/issue_2032_compile_diagnostic_string_for_top_level_decl_type.zig @@ -7,5 +7,5 @@ export fn entry() void { // backend=stage2 // target=native // -// :2:27: error: expected type 'u32', found 'tmp.tmp' +// :2:27: error: expected type 'u32', found 'tmp' // :1:1: note: struct declared here diff --git a/test/cases/x86_64-linux/hello_world_with_updates.0.zig b/test/cases/x86_64-linux/hello_world_with_updates.0.zig index c9c94442d0047544c55f9193bb7810a90b5c6088..40abdd6c1fa4217b99f077793ecbb56bfa3f89a0 100644 --- a/test/cases/x86_64-linux/hello_world_with_updates.0.zig +++ b/test/cases/x86_64-linux/hello_world_with_updates.0.zig @@ -2,5 +2,4 @@ // output_mode=Exe // target=x86_64-linux // -// :109:9: error: struct 'tmp.tmp' has no member named 'main' -// :7:1: note: struct declared here +// :109:9: error: root struct of file 'tmp' has no member named 'main' diff --git a/test/cases/x86_64-macos/hello_world_with_updates.0.zig b/test/cases/x86_64-macos/hello_world_with_updates.0.zig index 5860c9c0f6d8a0e2f860dc7aca28e01431a829cd..e0680c81d7420441fabd29498bf9258a5c16f291 100644 --- a/test/cases/x86_64-macos/hello_world_with_updates.0.zig +++ b/test/cases/x86_64-macos/hello_world_with_updates.0.zig @@ -2,5 +2,4 @@ // output_mode=Exe // target=x86_64-macos // -// :109:9: error: struct 'tmp.tmp' has no member named 'main' -// :7:1: note: struct declared here +// :109:9: error: root struct of file 'tmp' has no member named 'main' diff --git a/test/cases/x86_64-windows/hello_world_with_updates.0.zig b/test/cases/x86_64-windows/hello_world_with_updates.0.zig index 142699b9dac9ae5e4cb363be6db67623afa3c7c1..04e1d4cfad0ac9045fb033b9f550e2d5fb1e64c8 100644 --- a/test/cases/x86_64-windows/hello_world_with_updates.0.zig +++ b/test/cases/x86_64-windows/hello_world_with_updates.0.zig @@ -2,5 +2,4 @@ // output_mode=Exe // target=x86_64-windows // -// :130:9: error: struct 'tmp.tmp' has no member named 'main' -// :7:1: note: struct declared here +// :130:9: error: root struct of file 'tmp' has no member named 'main' -- 2.54.0 From 312260124279027a248d669e6096c3ab603fa188 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 29 Sep 2022 18:51:04 +0300 Subject: [PATCH 3/4] AstGen: do not set decl_line for containers Previously AstGen would set decl_line for containers so that declarations inside them would be relative to the start of the container but Sema was not aware of the line offset of the container and would make them relative to the containers parent decl which would then break for generic structs. In the future when working on incremental compilation it will likely be better to communicate the line delta to Sema but for now this is a simpler fix that correctly handles the non-incremental case. Closes #12725 Closes #12818 --- src/AstGen.zig | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/AstGen.zig b/src/AstGen.zig index 8e6721d7bca938d5166cb5651b1b6dbc8018e297..422827c673f6619dd8dfb167129e5d02af103146 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -4233,13 +4233,10 @@ fn structDeclInner( // are in scope, so that field types, alignments, and default value expressions // can refer to decls within the struct itself. astgen.advanceSourceCursorToNode(node); - // If `node == 0` then this is the root struct and all the declarations should - // be relative to the beginning of the file. - const decl_line = if (node == 0) 0 else astgen.source_line; var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, - .decl_line = decl_line, + .decl_line = gz.decl_line, .astgen = astgen, .force_comptime = true, .instructions = gz.instructions, @@ -4439,7 +4436,7 @@ fn unionDeclInner( var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, - .decl_line = astgen.source_line, + .decl_line = gz.decl_line, .astgen = astgen, .force_comptime = true, .instructions = gz.instructions, @@ -4722,7 +4719,7 @@ fn containerDecl( var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, - .decl_line = astgen.source_line, + .decl_line = gz.decl_line, .astgen = astgen, .force_comptime = true, .instructions = gz.instructions, @@ -4827,7 +4824,7 @@ fn containerDecl( var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, - .decl_line = astgen.source_line, + .decl_line = gz.decl_line, .astgen = astgen, .force_comptime = true, .instructions = gz.instructions, -- 2.54.0 From 2a4e89e0c9428b1ca59bc23c7c1d667c8ddb2304 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 29 Sep 2022 19:02:59 +0300 Subject: [PATCH 4/4] Type: correctly handle ABI align strat for optionals and error unions Closes #12984 --- src/type.zig | 20 ++++++++++++++++++-- test/behavior.zig | 1 + test/behavior/bugs/12984.zig | 22 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 test/behavior/bugs/12984.zig diff --git a/src/type.zig b/src/type.zig index 3e2e395d070b2f0c8002f37f1c14451d55088d3d..1fef52506242d8e2c95dc3ba46ef99886d79f72d 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3458,12 +3458,21 @@ pub const Type = extern union { else => {}, } + const payload_size = switch (try child_type.abiSizeAdvanced(target, strat)) { + .scalar => |elem_size| elem_size, + .val => switch (strat) { + .sema_kit => unreachable, + .eager => unreachable, + .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, + }, + }; + // Optional types are represented as a struct with the child type as the first // field and a boolean as the second. Since the child type's abi alignment is // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal // to the child type's ABI alignment. return AbiSizeAdvanced{ - .scalar = child_type.abiAlignment(target) + child_type.abiSize(target), + .scalar = child_type.abiAlignment(target) + payload_size, }; }, @@ -3478,7 +3487,14 @@ pub const Type = extern union { } const code_align = abiAlignment(Type.anyerror, target); const payload_align = abiAlignment(data.payload, target); - const payload_size = abiSize(data.payload, target); + const payload_size = switch (try data.payload.abiSizeAdvanced(target, strat)) { + .scalar => |elem_size| elem_size, + .val => switch (strat) { + .sema_kit => unreachable, + .eager => unreachable, + .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, + }, + }; var size: u64 = 0; if (code_align > payload_align) { diff --git a/test/behavior.zig b/test/behavior.zig index 019d9bbac74eafe01444fb9561718510fb85b18d..ed7910cfbcb3dd511a9a29c8c29b81883bc9b964 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -98,6 +98,7 @@ test { _ = @import("behavior/bugs/12911.zig"); _ = @import("behavior/bugs/12928.zig"); _ = @import("behavior/bugs/12945.zig"); + _ = @import("behavior/bugs/12984.zig"); _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); diff --git a/test/behavior/bugs/12984.zig b/test/behavior/bugs/12984.zig new file mode 100644 index 0000000000000000000000000000000000000000..a538b62e8d569e34249a2a0a0f727ee8abf735d5 --- /dev/null +++ b/test/behavior/bugs/12984.zig @@ -0,0 +1,22 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +pub fn DeleagateWithContext(comptime Function: type) type { + const ArgArgs = std.meta.ArgsTuple(Function); + return struct { + t: ArgArgs, + }; +} + +pub const OnConfirm = DeleagateWithContext(fn (bool) void); +pub const CustomDraw = DeleagateWithContext(fn (?OnConfirm) void); + +test "simple test" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var c: CustomDraw = undefined; + _ = c; +} -- 2.54.0