| ... | ... | @@ -1432,9 +1432,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1432 | 1432 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 1433 | 1433 | const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs); |
| 1434 | 1434 | const ptr = sema.resolveInst(bin_inst.rhs); |
| 1435 | | |
| 1436 | 1435 | const addr_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local); |
| 1437 | 1436 | |
| 1437 | // Needed for the call to `anon_decl.finish()` below which checks `ty.hasCodeGenBits()`. |
| 1438 | _ = try sema.typeHasOnePossibleValue(block, src, pointee_ty); |
| 1439 | |
| 1438 | 1440 | if (Air.refToIndex(ptr)) |ptr_inst| { |
| 1439 | 1441 | if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) { |
| 1440 | 1442 | const air_datas = sema.air_instructions.items(.data); |
| ... | ... | @@ -2076,7 +2078,8 @@ fn zirRetPtr( |
| 2076 | 2078 | try sema.requireFunctionBlock(block, src); |
| 2077 | 2079 | |
| 2078 | 2080 | if (block.is_comptime) { |
| 2079 | | return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty, 0); |
| 2081 | const fn_ret_ty = try sema.resolveTypeFields(block, src, sema.fn_ret_ty); |
| 2082 | return sema.analyzeComptimeAlloc(block, fn_ret_ty, 0, src); |
| 2080 | 2083 | } |
| 2081 | 2084 | |
| 2082 | 2085 | const ptr_type = try Type.ptr(sema.arena, .{ |
| ... | ... | @@ -2227,7 +2230,7 @@ fn zirAllocExtended( |
| 2227 | 2230 | |
| 2228 | 2231 | if (small.is_comptime) { |
| 2229 | 2232 | if (small.has_type) { |
| 2230 | | return sema.analyzeComptimeAlloc(block, var_ty, alignment); |
| 2233 | return sema.analyzeComptimeAlloc(block, var_ty, alignment, ty_src); |
| 2231 | 2234 | } else { |
| 2232 | 2235 | return sema.addConstant( |
| 2233 | 2236 | inferred_alloc_ty, |
| ... | ... | @@ -2273,7 +2276,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 2273 | 2276 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 2274 | 2277 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 2275 | 2278 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 2276 | | return sema.analyzeComptimeAlloc(block, var_ty, 0); |
| 2279 | return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src); |
| 2277 | 2280 | } |
| 2278 | 2281 | |
| 2279 | 2282 | fn zirAllocInferredComptime(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -2295,7 +2298,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 2295 | 2298 | const var_decl_src = inst_data.src(); |
| 2296 | 2299 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 2297 | 2300 | if (block.is_comptime) { |
| 2298 | | return sema.analyzeComptimeAlloc(block, var_ty, 0); |
| 2301 | return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src); |
| 2299 | 2302 | } |
| 2300 | 2303 | const ptr_type = try Type.ptr(sema.arena, .{ |
| 2301 | 2304 | .pointee_type = var_ty, |
| ... | ... | @@ -2315,7 +2318,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 2315 | 2318 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 2316 | 2319 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 2317 | 2320 | if (block.is_comptime) { |
| 2318 | | return sema.analyzeComptimeAlloc(block, var_ty, 0); |
| 2321 | return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src); |
| 2319 | 2322 | } |
| 2320 | 2323 | try sema.validateVarType(block, ty_src, var_ty, false); |
| 2321 | 2324 | const ptr_type = try Type.ptr(sema.arena, .{ |
| ... | ... | @@ -4261,14 +4264,14 @@ fn analyzeCall( |
| 4261 | 4264 | const arg_src = call_src; // TODO: better source location |
| 4262 | 4265 | if (i < fn_params_len) { |
| 4263 | 4266 | const param_ty = func_ty.fnParamType(i); |
| 4264 | | try sema.resolveTypeLayout(block, arg_src, param_ty); |
| 4267 | try sema.resolveTypeForCodegen(block, arg_src, param_ty); |
| 4265 | 4268 | args[i] = try sema.coerce(block, param_ty, uncasted_arg, arg_src); |
| 4266 | 4269 | } else { |
| 4267 | 4270 | args[i] = uncasted_arg; |
| 4268 | 4271 | } |
| 4269 | 4272 | } |
| 4270 | 4273 | |
| 4271 | | try sema.resolveTypeLayout(block, call_src, func_ty_info.return_type); |
| 4274 | try sema.resolveTypeForCodegen(block, call_src, func_ty_info.return_type); |
| 4272 | 4275 | |
| 4273 | 4276 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + |
| 4274 | 4277 | args.len); |
| ... | ... | @@ -4338,7 +4341,7 @@ fn finishGenericCall( |
| 4338 | 4341 | const param_ty = new_fn_ty.fnParamType(runtime_i); |
| 4339 | 4342 | const arg_src = call_src; // TODO: better source location |
| 4340 | 4343 | const uncasted_arg = uncasted_args[total_i]; |
| 4341 | | try sema.resolveTypeLayout(block, arg_src, param_ty); |
| 4344 | try sema.resolveTypeForCodegen(block, arg_src, param_ty); |
| 4342 | 4345 | const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); |
| 4343 | 4346 | runtime_args[runtime_i] = casted_arg; |
| 4344 | 4347 | runtime_i += 1; |
| ... | ... | @@ -4346,7 +4349,7 @@ fn finishGenericCall( |
| 4346 | 4349 | total_i += 1; |
| 4347 | 4350 | } |
| 4348 | 4351 | |
| 4349 | | try sema.resolveTypeLayout(block, call_src, new_fn_ty.fnReturnType()); |
| 4352 | try sema.resolveTypeForCodegen(block, call_src, new_fn_ty.fnReturnType()); |
| 4350 | 4353 | } |
| 4351 | 4354 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + |
| 4352 | 4355 | runtime_args_len); |
| ... | ... | @@ -8751,7 +8754,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 8751 | 8754 | .AnyFrame, |
| 8752 | 8755 | => operand_ty.abiSize(target), |
| 8753 | 8756 | }; |
| 8754 | | return sema.addIntUnsigned(Type.initTag(.comptime_int), abi_size); |
| 8757 | return sema.addIntUnsigned(Type.comptime_int, abi_size); |
| 8755 | 8758 | } |
| 8756 | 8759 | |
| 8757 | 8760 | fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -12429,7 +12432,7 @@ fn coerce( |
| 12429 | 12432 | const arena = sema.arena; |
| 12430 | 12433 | const target = sema.mod.getTarget(); |
| 12431 | 12434 | |
| 12432 | | const in_memory_result = try sema.coerceInMemoryAllowed(dest_ty, inst_ty, false, target); |
| 12435 | const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src); |
| 12433 | 12436 | if (in_memory_result == .ok) { |
| 12434 | 12437 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 12435 | 12438 | // Keep the comptime Value representation; take the new type. |
| ... | ... | @@ -12482,7 +12485,7 @@ fn coerce( |
| 12482 | 12485 | if (inst_ty.isConstPtr() and dest_is_mut) break :single_item; |
| 12483 | 12486 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :single_item; |
| 12484 | 12487 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :single_item; |
| 12485 | | switch (try sema.coerceInMemoryAllowed(array_elem_ty, ptr_elem_ty, dest_is_mut, target)) { |
| 12488 | switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) { |
| 12486 | 12489 | .ok => {}, |
| 12487 | 12490 | .no_match => break :single_item, |
| 12488 | 12491 | } |
| ... | ... | @@ -12494,14 +12497,16 @@ fn coerce( |
| 12494 | 12497 | if (!inst_ty.isSinglePointer()) break :src_array_ptr; |
| 12495 | 12498 | const array_ty = inst_ty.childType(); |
| 12496 | 12499 | if (array_ty.zigTypeTag() != .Array) break :src_array_ptr; |
| 12497 | | const array_elem_type = array_ty.childType(); |
| 12500 | const len0 = array_ty.arrayLen() == 0; |
| 12501 | // We resolve here so that the backend has the layout of the elem type. |
| 12502 | const array_elem_type = try sema.resolveTypeFields(block, inst_src, array_ty.childType()); |
| 12498 | 12503 | const dest_is_mut = dest_info.mutable; |
| 12499 | | if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr; |
| 12504 | if (inst_ty.isConstPtr() and dest_is_mut and !len0) break :src_array_ptr; |
| 12500 | 12505 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :src_array_ptr; |
| 12501 | 12506 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :src_array_ptr; |
| 12502 | 12507 | |
| 12503 | 12508 | const dst_elem_type = dest_info.pointee_type; |
| 12504 | | switch (try sema.coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, target)) { |
| 12509 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src)) { |
| 12505 | 12510 | .ok => {}, |
| 12506 | 12511 | .no_match => break :src_array_ptr, |
| 12507 | 12512 | } |
| ... | ... | @@ -12540,7 +12545,7 @@ fn coerce( |
| 12540 | 12545 | const src_elem_ty = inst_ty.childType(); |
| 12541 | 12546 | const dest_is_mut = dest_info.mutable; |
| 12542 | 12547 | const dst_elem_type = dest_info.pointee_type; |
| 12543 | | switch (try sema.coerceInMemoryAllowed(dst_elem_type, src_elem_ty, dest_is_mut, target)) { |
| 12548 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) { |
| 12544 | 12549 | .ok => {}, |
| 12545 | 12550 | .no_match => break :src_c_ptr, |
| 12546 | 12551 | } |
| ... | ... | @@ -12738,10 +12743,13 @@ const InMemoryCoercionResult = enum { |
| 12738 | 12743 | /// look at the function types_match_const_cast_only |
| 12739 | 12744 | fn coerceInMemoryAllowed( |
| 12740 | 12745 | sema: *Sema, |
| 12746 | block: *Block, |
| 12741 | 12747 | dest_ty: Type, |
| 12742 | 12748 | src_ty: Type, |
| 12743 | 12749 | dest_is_mut: bool, |
| 12744 | 12750 | target: std.Target, |
| 12751 | dest_src: LazySrcLoc, |
| 12752 | src_src: LazySrcLoc, |
| 12745 | 12753 | ) CompileError!InMemoryCoercionResult { |
| 12746 | 12754 | if (dest_ty.eql(src_ty)) |
| 12747 | 12755 | return .ok; |
| ... | ... | @@ -12749,15 +12757,15 @@ fn coerceInMemoryAllowed( |
| 12749 | 12757 | // Pointers / Pointer-like Optionals |
| 12750 | 12758 | var dest_buf: Type.Payload.ElemType = undefined; |
| 12751 | 12759 | var src_buf: Type.Payload.ElemType = undefined; |
| 12752 | | if (dest_ty.ptrOrOptionalPtrTy(&dest_buf)) |dest_ptr_ty| { |
| 12753 | | if (src_ty.ptrOrOptionalPtrTy(&src_buf)) |src_ptr_ty| { |
| 12754 | | return try sema.coerceInMemoryAllowedPtrs(dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut, target); |
| 12760 | if (try sema.typePtrOrOptionalPtrTy(block, dest_ty, &dest_buf, dest_src)) |dest_ptr_ty| { |
| 12761 | if (try sema.typePtrOrOptionalPtrTy(block, src_ty, &src_buf, src_src)) |src_ptr_ty| { |
| 12762 | return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut, target, dest_src, src_src); |
| 12755 | 12763 | } |
| 12756 | 12764 | } |
| 12757 | 12765 | |
| 12758 | 12766 | // Slices |
| 12759 | 12767 | if (dest_ty.isSlice() and src_ty.isSlice()) { |
| 12760 | | return try sema.coerceInMemoryAllowedPtrs(dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target); |
| 12768 | return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); |
| 12761 | 12769 | } |
| 12762 | 12770 | |
| 12763 | 12771 | const dest_tag = dest_ty.zigTypeTag(); |
| ... | ... | @@ -12765,16 +12773,16 @@ fn coerceInMemoryAllowed( |
| 12765 | 12773 | |
| 12766 | 12774 | // Functions |
| 12767 | 12775 | if (dest_tag == .Fn and src_tag == .Fn) { |
| 12768 | | return try sema.coerceInMemoryAllowedFns(dest_ty, src_ty, target); |
| 12776 | return try sema.coerceInMemoryAllowedFns(block, dest_ty, src_ty, target, dest_src, src_src); |
| 12769 | 12777 | } |
| 12770 | 12778 | |
| 12771 | 12779 | // Error Unions |
| 12772 | 12780 | if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) { |
| 12773 | | const child = try sema.coerceInMemoryAllowed(dest_ty.errorUnionPayload(), src_ty.errorUnionPayload(), dest_is_mut, target); |
| 12781 | const child = try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionPayload(), src_ty.errorUnionPayload(), dest_is_mut, target, dest_src, src_src); |
| 12774 | 12782 | if (child == .no_match) { |
| 12775 | 12783 | return child; |
| 12776 | 12784 | } |
| 12777 | | return try sema.coerceInMemoryAllowed(dest_ty.errorUnionSet(), src_ty.errorUnionSet(), dest_is_mut, target); |
| 12785 | return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(), src_ty.errorUnionSet(), dest_is_mut, target, dest_src, src_src); |
| 12778 | 12786 | } |
| 12779 | 12787 | |
| 12780 | 12788 | // Error Sets |
| ... | ... | @@ -12884,9 +12892,12 @@ fn coerceInMemoryAllowedErrorSets( |
| 12884 | 12892 | |
| 12885 | 12893 | fn coerceInMemoryAllowedFns( |
| 12886 | 12894 | sema: *Sema, |
| 12895 | block: *Block, |
| 12887 | 12896 | dest_ty: Type, |
| 12888 | 12897 | src_ty: Type, |
| 12889 | 12898 | target: std.Target, |
| 12899 | dest_src: LazySrcLoc, |
| 12900 | src_src: LazySrcLoc, |
| 12890 | 12901 | ) !InMemoryCoercionResult { |
| 12891 | 12902 | const dest_info = dest_ty.fnInfo(); |
| 12892 | 12903 | const src_info = src_ty.fnInfo(); |
| ... | ... | @@ -12900,7 +12911,7 @@ fn coerceInMemoryAllowedFns( |
| 12900 | 12911 | } |
| 12901 | 12912 | |
| 12902 | 12913 | if (!src_info.return_type.isNoReturn()) { |
| 12903 | | const rt = try sema.coerceInMemoryAllowed(dest_info.return_type, src_info.return_type, false, target); |
| 12914 | const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type, src_info.return_type, false, target, dest_src, src_src); |
| 12904 | 12915 | if (rt == .no_match) { |
| 12905 | 12916 | return rt; |
| 12906 | 12917 | } |
| ... | ... | @@ -12920,7 +12931,7 @@ fn coerceInMemoryAllowedFns( |
| 12920 | 12931 | // TODO: nolias |
| 12921 | 12932 | |
| 12922 | 12933 | // Note: Cast direction is reversed here. |
| 12923 | | const param = try sema.coerceInMemoryAllowed(src_param_ty, dest_param_ty, false, target); |
| 12934 | const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src); |
| 12924 | 12935 | if (param == .no_match) { |
| 12925 | 12936 | return param; |
| 12926 | 12937 | } |
| ... | ... | @@ -12935,17 +12946,20 @@ fn coerceInMemoryAllowedFns( |
| 12935 | 12946 | |
| 12936 | 12947 | fn coerceInMemoryAllowedPtrs( |
| 12937 | 12948 | sema: *Sema, |
| 12949 | block: *Block, |
| 12938 | 12950 | dest_ty: Type, |
| 12939 | 12951 | src_ty: Type, |
| 12940 | 12952 | dest_ptr_ty: Type, |
| 12941 | 12953 | src_ptr_ty: Type, |
| 12942 | 12954 | dest_is_mut: bool, |
| 12943 | 12955 | target: std.Target, |
| 12956 | dest_src: LazySrcLoc, |
| 12957 | src_src: LazySrcLoc, |
| 12944 | 12958 | ) !InMemoryCoercionResult { |
| 12945 | 12959 | const dest_info = dest_ptr_ty.ptrInfo().data; |
| 12946 | 12960 | const src_info = src_ptr_ty.ptrInfo().data; |
| 12947 | 12961 | |
| 12948 | | const child = try sema.coerceInMemoryAllowed(dest_info.pointee_type, src_info.pointee_type, dest_info.mutable, target); |
| 12962 | const child = try sema.coerceInMemoryAllowed(block, dest_info.pointee_type, src_info.pointee_type, dest_info.mutable, target, dest_src, src_src); |
| 12949 | 12963 | if (child == .no_match) { |
| 12950 | 12964 | return child; |
| 12951 | 12965 | } |
| ... | ... | @@ -13592,7 +13606,7 @@ fn coerceVectorInMemory( |
| 13592 | 13606 | const target = sema.mod.getTarget(); |
| 13593 | 13607 | const dest_elem_ty = dest_ty.childType(); |
| 13594 | 13608 | const inst_elem_ty = inst_ty.childType(); |
| 13595 | | const in_memory_result = try sema.coerceInMemoryAllowed(dest_elem_ty, inst_elem_ty, false, target); |
| 13609 | const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, false, target, dest_ty_src, inst_src); |
| 13596 | 13610 | if (in_memory_result != .ok) { |
| 13597 | 13611 | // TODO recursive error notes for coerceInMemoryAllowed failure |
| 13598 | 13612 | return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_ty, inst_ty }); |
| ... | ... | @@ -14351,12 +14365,12 @@ fn resolvePeerTypes( |
| 14351 | 14365 | .Optional => { |
| 14352 | 14366 | var opt_child_buf: Type.Payload.ElemType = undefined; |
| 14353 | 14367 | const opt_child_ty = candidate_ty.optionalChild(&opt_child_buf); |
| 14354 | | if ((try sema.coerceInMemoryAllowed(opt_child_ty, chosen_ty, false, target)) == .ok) { |
| 14368 | if ((try sema.coerceInMemoryAllowed(block, opt_child_ty, chosen_ty, false, target, src, src)) == .ok) { |
| 14355 | 14369 | chosen = candidate; |
| 14356 | 14370 | chosen_i = candidate_i + 1; |
| 14357 | 14371 | continue; |
| 14358 | 14372 | } |
| 14359 | | if ((try sema.coerceInMemoryAllowed(chosen_ty, opt_child_ty, false, target)) == .ok) { |
| 14373 | if ((try sema.coerceInMemoryAllowed(block, chosen_ty, opt_child_ty, false, target, src, src)) == .ok) { |
| 14360 | 14374 | any_are_null = true; |
| 14361 | 14375 | continue; |
| 14362 | 14376 | } |
| ... | ... | @@ -14379,10 +14393,10 @@ fn resolvePeerTypes( |
| 14379 | 14393 | .Optional => { |
| 14380 | 14394 | var opt_child_buf: Type.Payload.ElemType = undefined; |
| 14381 | 14395 | const opt_child_ty = chosen_ty.optionalChild(&opt_child_buf); |
| 14382 | | if ((try sema.coerceInMemoryAllowed(opt_child_ty, candidate_ty, false, target)) == .ok) { |
| 14396 | if ((try sema.coerceInMemoryAllowed(block, opt_child_ty, candidate_ty, false, target, src, src)) == .ok) { |
| 14383 | 14397 | continue; |
| 14384 | 14398 | } |
| 14385 | | if ((try sema.coerceInMemoryAllowed(candidate_ty, opt_child_ty, false, target)) == .ok) { |
| 14399 | if ((try sema.coerceInMemoryAllowed(block, candidate_ty, opt_child_ty, false, target, src, src)) == .ok) { |
| 14386 | 14400 | any_are_null = true; |
| 14387 | 14401 | chosen = candidate; |
| 14388 | 14402 | chosen_i = candidate_i + 1; |
| ... | ... | @@ -14439,38 +14453,8 @@ pub fn resolveTypeLayout( |
| 14439 | 14453 | ty: Type, |
| 14440 | 14454 | ) CompileError!void { |
| 14441 | 14455 | switch (ty.zigTypeTag()) { |
| 14442 | | .Struct => { |
| 14443 | | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 14444 | | const struct_obj = resolved_ty.castTag(.@"struct").?.data; |
| 14445 | | switch (struct_obj.status) { |
| 14446 | | .none, .have_field_types => {}, |
| 14447 | | .field_types_wip, .layout_wip => { |
| 14448 | | return sema.fail(block, src, "struct {} depends on itself", .{ty}); |
| 14449 | | }, |
| 14450 | | .have_layout => return, |
| 14451 | | } |
| 14452 | | struct_obj.status = .layout_wip; |
| 14453 | | for (struct_obj.fields.values()) |field| { |
| 14454 | | try sema.resolveTypeLayout(block, src, field.ty); |
| 14455 | | } |
| 14456 | | struct_obj.status = .have_layout; |
| 14457 | | }, |
| 14458 | | .Union => { |
| 14459 | | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 14460 | | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |
| 14461 | | switch (union_obj.status) { |
| 14462 | | .none, .have_field_types => {}, |
| 14463 | | .field_types_wip, .layout_wip => { |
| 14464 | | return sema.fail(block, src, "union {} depends on itself", .{ty}); |
| 14465 | | }, |
| 14466 | | .have_layout => return, |
| 14467 | | } |
| 14468 | | union_obj.status = .layout_wip; |
| 14469 | | for (union_obj.fields.values()) |field| { |
| 14470 | | try sema.resolveTypeLayout(block, src, field.ty); |
| 14471 | | } |
| 14472 | | union_obj.status = .have_layout; |
| 14473 | | }, |
| 14456 | .Struct => return sema.resolveStructLayout(block, src, ty), |
| 14457 | .Union => return sema.resolveUnionLayout(block, src, ty), |
| 14474 | 14458 | .Array => { |
| 14475 | 14459 | const elem_ty = ty.childType(); |
| 14476 | 14460 | return sema.resolveTypeLayout(block, src, elem_ty); |
| ... | ... | @@ -14488,6 +14472,73 @@ pub fn resolveTypeLayout( |
| 14488 | 14472 | } |
| 14489 | 14473 | } |
| 14490 | 14474 | |
| 14475 | fn resolveStructLayout( |
| 14476 | sema: *Sema, |
| 14477 | block: *Block, |
| 14478 | src: LazySrcLoc, |
| 14479 | ty: Type, |
| 14480 | ) CompileError!void { |
| 14481 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 14482 | const struct_obj = resolved_ty.castTag(.@"struct").?.data; |
| 14483 | switch (struct_obj.status) { |
| 14484 | .none, .have_field_types => {}, |
| 14485 | .field_types_wip, .layout_wip => { |
| 14486 | return sema.fail(block, src, "struct {} depends on itself", .{ty}); |
| 14487 | }, |
| 14488 | .have_layout => return, |
| 14489 | } |
| 14490 | struct_obj.status = .layout_wip; |
| 14491 | for (struct_obj.fields.values()) |field| { |
| 14492 | try sema.resolveTypeLayout(block, src, field.ty); |
| 14493 | } |
| 14494 | struct_obj.status = .have_layout; |
| 14495 | } |
| 14496 | |
| 14497 | fn resolveUnionLayout( |
| 14498 | sema: *Sema, |
| 14499 | block: *Block, |
| 14500 | src: LazySrcLoc, |
| 14501 | ty: Type, |
| 14502 | ) CompileError!void { |
| 14503 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 14504 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |
| 14505 | switch (union_obj.status) { |
| 14506 | .none, .have_field_types => {}, |
| 14507 | .field_types_wip, .layout_wip => { |
| 14508 | return sema.fail(block, src, "union {} depends on itself", .{ty}); |
| 14509 | }, |
| 14510 | .have_layout => return, |
| 14511 | } |
| 14512 | union_obj.status = .layout_wip; |
| 14513 | for (union_obj.fields.values()) |field| { |
| 14514 | try sema.resolveTypeLayout(block, src, field.ty); |
| 14515 | } |
| 14516 | union_obj.status = .have_layout; |
| 14517 | } |
| 14518 | |
| 14519 | fn resolveTypeForCodegen( |
| 14520 | sema: *Sema, |
| 14521 | block: *Block, |
| 14522 | src: LazySrcLoc, |
| 14523 | ty: Type, |
| 14524 | ) CompileError!void { |
| 14525 | switch (ty.zigTypeTag()) { |
| 14526 | .Pointer => { |
| 14527 | const child_ty = try sema.resolveTypeFields(block, src, ty.childType()); |
| 14528 | return resolveTypeForCodegen(sema, block, src, child_ty); |
| 14529 | }, |
| 14530 | .Struct => return resolveStructLayout(sema, block, src, ty), |
| 14531 | .Union => return resolveUnionLayout(sema, block, src, ty), |
| 14532 | .Array => return resolveTypeForCodegen(sema, block, src, ty.childType()), |
| 14533 | .Optional => { |
| 14534 | var buf: Type.Payload.ElemType = undefined; |
| 14535 | return resolveTypeForCodegen(sema, block, src, ty.optionalChild(&buf)); |
| 14536 | }, |
| 14537 | .ErrorUnion => return resolveTypeForCodegen(sema, block, src, ty.errorUnionPayload()), |
| 14538 | else => {}, |
| 14539 | } |
| 14540 | } |
| 14541 | |
| 14491 | 14542 | fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type { |
| 14492 | 14543 | switch (ty.tag()) { |
| 14493 | 14544 | .@"struct" => { |
| ... | ... | @@ -15215,11 +15266,20 @@ fn typeHasOnePossibleValue( |
| 15215 | 15266 | return null; |
| 15216 | 15267 | } |
| 15217 | 15268 | }, |
| 15218 | | .@"union" => { |
| 15219 | | return null; // TODO |
| 15220 | | }, |
| 15221 | | .union_tagged => { |
| 15222 | | return null; // TODO |
| 15269 | .@"union", .union_tagged => { |
| 15270 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 15271 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |
| 15272 | const tag_val = (try sema.typeHasOnePossibleValue(block, src, union_obj.tag_ty)) orelse |
| 15273 | return null; |
| 15274 | const only_field = union_obj.fields.values()[0]; |
| 15275 | const val_val = (try sema.typeHasOnePossibleValue(block, src, only_field.ty)) orelse |
| 15276 | return null; |
| 15277 | // TODO make this not allocate. The function in `Type.onePossibleValue` |
| 15278 | // currently returns `empty_struct_value` and we should do that here too. |
| 15279 | return try Value.Tag.@"union".create(sema.arena, .{ |
| 15280 | .tag = tag_val, |
| 15281 | .val = val_val, |
| 15282 | }); |
| 15223 | 15283 | }, |
| 15224 | 15284 | |
| 15225 | 15285 | .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), |
| ... | ... | @@ -15453,7 +15513,11 @@ fn analyzeComptimeAlloc( |
| 15453 | 15513 | block: *Block, |
| 15454 | 15514 | var_type: Type, |
| 15455 | 15515 | alignment: u32, |
| 15516 | src: LazySrcLoc, |
| 15456 | 15517 | ) CompileError!Air.Inst.Ref { |
| 15518 | // Needed to make an anon decl with type `var_type` (the `finish()` call below). |
| 15519 | _ = try sema.typeHasOnePossibleValue(block, src, var_type); |
| 15520 | |
| 15457 | 15521 | const ptr_type = try Type.ptr(sema.arena, .{ |
| 15458 | 15522 | .pointee_type = var_type, |
| 15459 | 15523 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), |
| ... | ... | @@ -15551,8 +15615,8 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 15551 | 15615 | // We have a Value that lines up in virtual memory exactly with what we want to load. |
| 15552 | 15616 | // If the Type is in-memory coercable to `load_ty`, it may be returned without modifications. |
| 15553 | 15617 | const coerce_in_mem_ok = |
| 15554 | | (try sema.coerceInMemoryAllowed(load_ty, parent.ty, false, target)) == .ok or |
| 15555 | | (try sema.coerceInMemoryAllowed(parent.ty, load_ty, false, target)) == .ok; |
| 15618 | (try sema.coerceInMemoryAllowed(block, load_ty, parent.ty, false, target, src, src)) == .ok or |
| 15619 | (try sema.coerceInMemoryAllowed(block, parent.ty, load_ty, false, target, src, src)) == .ok; |
| 15556 | 15620 | if (coerce_in_mem_ok) { |
| 15557 | 15621 | if (parent.is_mutable) { |
| 15558 | 15622 | // The decl whose value we are obtaining here may be overwritten with |
| ... | ... | @@ -15588,3 +15652,64 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError |
| 15588 | 15652 | error.Overflow => return sema.fail(block, src, "expression produces integer value {d} which is too big for this compiler implementation to handle", .{int}), |
| 15589 | 15653 | }; |
| 15590 | 15654 | } |
| 15655 | |
| 15656 | /// For pointer-like optionals, it returns the pointer type. For pointers, |
| 15657 | /// the type is returned unmodified. |
| 15658 | /// This can return `error.AnalysisFail` because it sometimes requires resolving whether |
| 15659 | /// a type has zero bits, which can cause a "foo depends on itself" compile error. |
| 15660 | /// This logic must be kept in sync with `Type.isPtrLikeOptional`. |
| 15661 | fn typePtrOrOptionalPtrTy( |
| 15662 | sema: *Sema, |
| 15663 | block: *Block, |
| 15664 | ty: Type, |
| 15665 | buf: *Type.Payload.ElemType, |
| 15666 | src: LazySrcLoc, |
| 15667 | ) !?Type { |
| 15668 | switch (ty.tag()) { |
| 15669 | .optional_single_const_pointer, |
| 15670 | .optional_single_mut_pointer, |
| 15671 | .c_const_pointer, |
| 15672 | .c_mut_pointer, |
| 15673 | => return ty.optionalChild(buf), |
| 15674 | |
| 15675 | .single_const_pointer_to_comptime_int, |
| 15676 | .single_const_pointer, |
| 15677 | .single_mut_pointer, |
| 15678 | .many_const_pointer, |
| 15679 | .many_mut_pointer, |
| 15680 | .manyptr_u8, |
| 15681 | .manyptr_const_u8, |
| 15682 | => return ty, |
| 15683 | |
| 15684 | .pointer => switch (ty.ptrSize()) { |
| 15685 | .Slice => return null, |
| 15686 | .C => return ty.optionalChild(buf), |
| 15687 | else => return ty, |
| 15688 | }, |
| 15689 | |
| 15690 | .inferred_alloc_const => unreachable, |
| 15691 | .inferred_alloc_mut => unreachable, |
| 15692 | |
| 15693 | .optional => { |
| 15694 | const child_type = ty.optionalChild(buf); |
| 15695 | if (child_type.zigTypeTag() != .Pointer) return null; |
| 15696 | |
| 15697 | const info = child_type.ptrInfo().data; |
| 15698 | switch (info.size) { |
| 15699 | .Slice, .C => return null, |
| 15700 | .Many, .One => { |
| 15701 | if (info.@"allowzero") return null; |
| 15702 | |
| 15703 | // optionals of zero sized types behave like bools, not pointers |
| 15704 | if ((try sema.typeHasOnePossibleValue(block, src, child_type)) != null) { |
| 15705 | return null; |
| 15706 | } |
| 15707 | |
| 15708 | return child_type; |
| 15709 | }, |
| 15710 | } |
| 15711 | }, |
| 15712 | |
| 15713 | else => return null, |
| 15714 | } |
| 15715 | } |