From 9dba8eef5b07c9242a3ff786e22af11437f4ce38 Mon Sep 17 00:00:00 2001 From: agra Date: Tue, 24 Feb 2026 19:31:10 +0200 Subject: [PATCH] xxx --- examples/issue-0006.sx | 23 +++++++++++++++++++++++ examples/issue-0007.sx | 39 +++++++++++++++++++++++++++++++++++++++ examples/modules/stb.sx | 3 +++ src/codegen.zig | 11 +++++++---- 4 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 examples/issue-0006.sx create mode 100644 examples/issue-0007.sx diff --git a/examples/issue-0006.sx b/examples/issue-0006.sx new file mode 100644 index 0000000..796149d --- /dev/null +++ b/examples/issue-0006.sx @@ -0,0 +1,23 @@ +// Issue: match on u8 value with enum result assigned to typed field +// The switch value is u8 but case constants are s64 (default int literal type). +// Compiler should cast case constants to match the switch value type. +// LLVM error: Switch constants must all be same type as switch value! + +out :: (str: string) -> void #builtin; + +Button :: enum { + none; + left; + middle; + right; +} + +main :: () { + val : u8 = 2; + result : Button = if val == { + case 1: .left; + case 2: .middle; + case 3: .right; + else: .none; + }; +} diff --git a/examples/issue-0007.sx b/examples/issue-0007.sx new file mode 100644 index 0000000..c086fec --- /dev/null +++ b/examples/issue-0007.sx @@ -0,0 +1,39 @@ +// Issue: chained method call on struct field operates on a copy +// `a.field.method()` where method takes *Self creates a temporary copy of `field` +// instead of borrowing `a.field` as a pointer. +// The mutation is lost because it modifies the copy, not the original. + +out :: (str: string) -> void #builtin; + +Counter :: struct { + value: s64; + + inc :: (self: *Counter) { + self.value += 1; + } +} + +Parent :: struct { + counter: Counter; +} + +main :: () { + p := Parent.{ counter = Counter.{ value = 0 } }; + + // This should increment p.counter.value, but the mutation is lost: + p.counter.inc(); + + if p.counter.value == 0 { + out("BUG: p.counter.value is still 0 after inc()\n"); + } else { + out("OK: p.counter.value is 1\n"); + } + + // Workaround: take explicit pointer + cp := @p.counter; + cp.inc(); + + if p.counter.value == 1 { + out("OK: workaround via pointer works\n"); + } +} diff --git a/examples/modules/stb.sx b/examples/modules/stb.sx index 05e26b2..2197cce 100644 --- a/examples/modules/stb.sx +++ b/examples/modules/stb.sx @@ -1,4 +1,7 @@ #import c { #include "vendors/stb_image/stb_image.h"; #source "vendors/stb_image/stb_image_impl.c"; + + #include "vendors/stb_image/stb_image_write.h"; + #source "vendors/stb_image/stb_image_write_impl.c"; }; diff --git a/src/codegen.zig b/src/codegen.zig index f43de02..aca9d17 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -6333,8 +6333,11 @@ pub const CodeGen = struct { return entry.ptr; } } - // Non-identifier expressions (e.g. field access, tuple element): - // generate value, store into temp alloca, return alloca pointer + // Field access / index: take address of the lvalue directly (no copy) + if (node.data == .field_access or node.data == .index_expr) { + return try self.genAddressOf(node); + } + // Other non-identifier expressions: copy into temp alloca if (node.data != .identifier) { const val = try self.genExpr(node); const llvm_ty = c.LLVMTypeOf(val); @@ -10459,8 +10462,8 @@ pub const CodeGen = struct { null; const i64_type = self.i64Type(); - // Enum/union case constants use the backing type; bool uses i1; others use i64 - const case_int_type = if (enum_name) |en| self.getEnumLLVMType(en) else if (union_name) |un| self.getEnumLLVMType(un) else if (subject_ty == .boolean) self.i1Type() else i64_type; + // Enum/union case constants use the backing type; bool uses i1; others must match subject LLVM type + const case_int_type = if (enum_name) |en| self.getEnumLLVMType(en) else if (union_name) |un| self.getEnumLLVMType(un) else if (subject_ty == .boolean) self.i1Type() else c.LLVMTypeOf(subject_val); const merge_bb = self.appendBB("match_end"); // Create case basic blocks