diff --git a/src/AstGen.zig b/src/AstGen.zig index 8e6721d7bc..422827c673 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, diff --git a/src/Module.zig b/src/Module.zig index e756cc3dfd..6056c385e3 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 5e65132510..aed09d6201 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, @@ -21664,14 +21669,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 +21698,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/src/type.zig b/src/type.zig index 3e2e395d07..1fef525062 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 019d9bbac7..ed7910cfbc 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 0000000000..a538b62e8d --- /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; +} diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index e5cb8ea408..5aeb6a3414 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)); +} 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 3c7a494180..9f516ff139 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 b675fd941c..be222e5393 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 9ae320650a..d78891bb2b 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 c9c94442d0..40abdd6c1f 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 5860c9c0f6..e0680c81d7 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 142699b9da..04e1d4cfad 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'