diff --git a/src/codegen.zig b/src/codegen.zig index d3e1efc..1e33d97 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -4085,12 +4085,35 @@ pub const CodeGen = struct { return self.genSliceLiteral(node.data.array_literal, target_ty); } + // Infer source type once for all coercion checks below + const src_ty = self.inferType(node); + // Array to slice coercion: [N]T → []T - if (target_ty.isSlice()) { - const src_ty = self.inferType(node); - if (src_ty.isArray()) { - const arr_info = src_ty.array_type; - // Get the alloca pointer for the array (not the loaded value) + if (target_ty.isSlice() and src_ty.isArray()) { + const arr_info = src_ty.array_type; + // Get the alloca pointer for the array (not the loaded value) + const arr_alloca = blk: { + if (node.data == .identifier) { + if (self.named_values.get(node.data.identifier.name)) |entry| { + break :blk entry.ptr; + } + } + if (node.data == .field_access) { + break :blk try self.genAddressOf(node); + } + // Fallback: generate the expression and hope it returns a pointer + break :blk try self.genExpr(node); + }; + // GEP to get pointer to first element + const elem_ptr = self.arrayDecayToPointer(self.typeToLLVM(src_ty), arr_alloca, "arr_data"); + // Build slice struct {ptr, len} + return self.buildFatPointer(self.getStringStructType(), elem_ptr, self.constInt64(arr_info.length)); + } + + // Array to many-pointer coercion: [N]T → [*]T + if (target_ty.isManyPointer() and src_ty.isArray()) { + const arr_info = src_ty.array_type; + if (std.mem.eql(u8, arr_info.element_name, target_ty.many_pointer_type.element_name)) { const arr_alloca = blk: { if (node.data == .identifier) { if (self.named_values.get(node.data.identifier.name)) |entry| { @@ -4100,52 +4123,22 @@ pub const CodeGen = struct { if (node.data == .field_access) { break :blk try self.genAddressOf(node); } - // Fallback: generate the expression and hope it returns a pointer break :blk try self.genExpr(node); }; - // GEP to get pointer to first element - const elem_ptr = self.arrayDecayToPointer(self.typeToLLVM(src_ty), arr_alloca, "arr_data"); - // Build slice struct {ptr, len} - return self.buildFatPointer(self.getStringStructType(), elem_ptr, self.constInt64(arr_info.length)); - } - } - - // Array to many-pointer coercion: [N]T → [*]T - if (target_ty.isManyPointer()) { - const src_ty = self.inferType(node); - if (src_ty.isArray()) { - const arr_info = src_ty.array_type; - if (std.mem.eql(u8, arr_info.element_name, target_ty.many_pointer_type.element_name)) { - const arr_alloca = blk: { - if (node.data == .identifier) { - if (self.named_values.get(node.data.identifier.name)) |entry| { - break :blk entry.ptr; - } - } - if (node.data == .field_access) { - break :blk try self.genAddressOf(node); - } - break :blk try self.genExpr(node); - }; - return self.arrayDecayToPointer(self.typeToLLVM(src_ty), arr_alloca, "arr_decay"); - } + return self.arrayDecayToPointer(self.typeToLLVM(src_ty), arr_alloca, "arr_decay"); } } // Slice to many-pointer coercion: []T → [*]T (extract .ptr from fat pointer) - if (target_ty.isManyPointer()) { - const src_ty = self.inferType(node); - if (src_ty.isSlice()) { - if (std.mem.eql(u8, src_ty.slice_type.element_name, target_ty.many_pointer_type.element_name)) { - const slice_val = try self.genExpr(node); - return self.extractValue(slice_val, 0, "slice_decay"); - } + if (target_ty.isManyPointer() and src_ty.isSlice()) { + if (std.mem.eql(u8, src_ty.slice_type.element_name, target_ty.many_pointer_type.element_name)) { + const slice_val = try self.genExpr(node); + return self.extractValue(slice_val, 0, "slice_decay"); } } // Implicit address-of: passing T where *T is expected → auto & if (target_ty.isPointer()) { - const src_ty = self.inferType(node); const pointee_name = target_ty.pointer_type.pointee_name; const src_matches = if (src_ty.isStruct()) std.mem.eql(u8, src_ty.struct_type, pointee_name) or @@ -4170,7 +4163,6 @@ pub const CodeGen = struct { } var val = try self.genExpr(node); - const src_ty = self.inferType(node); // Struct literals return alloca pointers — load the value for by-value passing if (src_ty.isStruct() and target_ty.isStruct()) {