diff --git a/src/Sema.zig b/src/Sema.zig index c39146ca5a..14037d030e 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2086,7 +2086,7 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, object_ty: Type, field_name: []const u8) CompileError { const mod = sema.mod; - const inner_ty = if (object_ty.isSinglePointer()) object_ty.childType() else object_ty; + const inner_ty = if (object_ty.isSinglePointer(mod)) object_ty.childType() else object_ty; if (inner_ty.zigTypeTag(mod) == .Optional) opt: { var buf: Type.Payload.ElemType = undefined; @@ -3412,8 +3412,9 @@ fn indexablePtrLen( src: LazySrcLoc, object: Air.Inst.Ref, ) CompileError!Air.Inst.Ref { + const mod = sema.mod; const object_ty = sema.typeOf(object); - const is_pointer_to = object_ty.isSinglePointer(); + const is_pointer_to = object_ty.isSinglePointer(mod); const indexable_ty = if (is_pointer_to) object_ty.childType() else object_ty; try checkIndexable(sema, block, src, indexable_ty); return sema.fieldVal(block, src, object, "len", src); @@ -12764,12 +12765,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .Pointer => try sema.resolveDefinedValue(block, rhs_src, rhs), else => unreachable, }) |rhs_val| { - const lhs_sub_val = if (lhs_ty.isSinglePointer()) + const lhs_sub_val = if (lhs_ty.isSinglePointer(mod)) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; - const rhs_sub_val = if (rhs_ty.isSinglePointer()) + const rhs_sub_val = if (rhs_ty.isSinglePointer(mod)) (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).? else rhs_val; @@ -13022,7 +13023,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { const final_len_including_sent = result_len + @boolToInt(lhs_info.sentinel != null); - const lhs_sub_val = if (lhs_ty.isSinglePointer()) + const lhs_sub_val = if (lhs_ty.isSinglePointer(mod)) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; @@ -17588,7 +17589,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const elem_ty = blk: { const air_inst = try sema.resolveInst(extra.data.elem_type); const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| { - if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer()) { + if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(mod)) { try sema.errNote(block, elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{}); } return err; @@ -23902,7 +23903,7 @@ fn fieldVal( // Zig allows dereferencing a single pointer during field lookup. Note that // we don't actually need to generate the dereference some field lookups, like the // length of arrays and other comptime operations. - const is_pointer_to = object_ty.isSinglePointer(); + const is_pointer_to = object_ty.isSinglePointer(mod); const inner_ty = if (is_pointer_to) object_ty.childType() @@ -24092,7 +24093,7 @@ fn fieldPtr( // Zig allows dereferencing a single pointer during field lookup. Note that // we don't actually need to generate the dereference some field lookups, like the // length of arrays and other comptime operations. - const is_pointer_to = object_ty.isSinglePointer(); + const is_pointer_to = object_ty.isSinglePointer(mod); const inner_ty = if (is_pointer_to) object_ty.childType() @@ -25622,7 +25623,7 @@ fn coerceExtra( // *T to *[1]T single_item: { if (dest_info.size != .One) break :single_item; - if (!inst_ty.isSinglePointer()) break :single_item; + if (!inst_ty.isSinglePointer(mod)) break :single_item; if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; const ptr_elem_ty = inst_ty.childType(); const array_ty = dest_info.pointee_type; @@ -25639,7 +25640,7 @@ fn coerceExtra( // Coercions where the source is a single pointer to an array. src_array_ptr: { - if (!inst_ty.isSinglePointer()) break :src_array_ptr; + if (!inst_ty.isSinglePointer(mod)) break :src_array_ptr; if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; const array_ty = inst_ty.childType(); if (array_ty.zigTypeTag(mod) != .Array) break :src_array_ptr; @@ -25794,7 +25795,7 @@ fn coerceExtra( .One => switch (dest_info.pointee_type.zigTypeTag(mod)) { .Union => { // pointer to anonymous struct to pointer to union - if (inst_ty.isSinglePointer() and + if (inst_ty.isSinglePointer(mod) and inst_ty.childType().isAnonStruct() and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) { @@ -25803,7 +25804,7 @@ fn coerceExtra( }, .Struct => { // pointer to anonymous struct to pointer to struct - if (inst_ty.isSinglePointer() and + if (inst_ty.isSinglePointer(mod) and inst_ty.childType().isAnonStruct() and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) { @@ -25815,7 +25816,7 @@ fn coerceExtra( }, .Array => { // pointer to tuple to pointer to array - if (inst_ty.isSinglePointer() and + if (inst_ty.isSinglePointer(mod) and inst_ty.childType().isTuple() and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) { @@ -25834,7 +25835,7 @@ fn coerceExtra( ); } - if (!inst_ty.isSinglePointer()) break :to_slice; + if (!inst_ty.isSinglePointer(mod)) break :to_slice; const inst_child_ty = inst_ty.childType(); if (!inst_child_ty.isTuple()) break :to_slice; @@ -30807,7 +30808,7 @@ fn resolvePeerTypes( .Vector => continue, else => {}, }, - .Fn => if (chosen_ty.isSinglePointer() and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag(mod) == .Fn) { + .Fn => if (chosen_ty.isSinglePointer(mod) and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag(mod) == .Fn) { if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(), candidate_ty, target, src, src)) { continue; } diff --git a/src/codegen/c.zig b/src/codegen/c.zig index a87f37b1c9..f4daa56a6d 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -3873,7 +3873,7 @@ fn airCmpOp( try reap(f, inst, &.{ data.lhs, data.rhs }); const rhs_ty = f.typeOf(data.rhs); - const need_cast = lhs_ty.isSinglePointer() or rhs_ty.isSinglePointer(); + const need_cast = lhs_ty.isSinglePointer(mod) or rhs_ty.isSinglePointer(mod); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, writer, lhs_ty); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2e42e8e3fc..5bc06e4bfc 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5929,7 +5929,7 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch - const ptr = if (ptr_ty.isSinglePointer()) ptr: { + const ptr = if (ptr_ty.isSinglePointer(mod)) ptr: { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); @@ -5962,7 +5962,7 @@ pub const FuncGen = struct { if (elem_ptr.ptrInfo().data.vector_index != .none) return base_ptr; const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty); - if (ptr_ty.isSinglePointer()) { + if (ptr_ty.isSinglePointer(mod)) { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); diff --git a/src/type.zig b/src/type.zig index 8fd0ea6869..934bfd35ca 100644 --- a/src/type.zig +++ b/src/type.zig @@ -4039,19 +4039,25 @@ pub const Type = struct { } } - pub fn isSinglePointer(self: Type) bool { - return switch (self.tag()) { - .single_const_pointer, - .single_mut_pointer, - .single_const_pointer_to_comptime_int, - .inferred_alloc_const, - .inferred_alloc_mut, - => true, + pub fn isSinglePointer(ty: Type, mod: *const Module) bool { + switch (ty.ip_index) { + .none => return switch (ty.tag()) { + .single_const_pointer, + .single_mut_pointer, + .single_const_pointer_to_comptime_int, + .inferred_alloc_const, + .inferred_alloc_mut, + => true, - .pointer => self.castTag(.pointer).?.data.size == .One, + .pointer => ty.castTag(.pointer).?.data.size == .One, - else => false, - }; + else => false, + }, + else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .ptr_type => |ptr_info| ptr_info.size == .One, + else => false, + }, + } } /// Asserts `ty` is a pointer. @@ -6142,6 +6148,11 @@ pub const Type = struct { } pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc { + if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .struct_type => @panic("TODO"), + .union_type => @panic("TODO"), + else => return null, + }; switch (ty.tag()) { .enum_full, .enum_nonexhaustive => { const enum_full = ty.cast(Payload.EnumFull).?.data;