| ... | @@ -1432,9 +1432,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -1432,9 +1432,11 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1432 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; | 1432 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 1433 | const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs); | 1433 | const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs); |
| 1434 | const ptr = sema.resolveInst(bin_inst.rhs); | 1434 | const ptr = sema.resolveInst(bin_inst.rhs); |
| 1435 | | | |
| 1436 | const addr_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local); | 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 | if (Air.refToIndex(ptr)) |ptr_inst| { | 1440 | if (Air.refToIndex(ptr)) |ptr_inst| { |
| 1439 | if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) { | 1441 | if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) { |
| 1440 | const air_datas = sema.air_instructions.items(.data); | 1442 | const air_datas = sema.air_instructions.items(.data); |
| ... | @@ -2076,7 +2078,8 @@ fn zirRetPtr( | ... | @@ -2076,7 +2078,8 @@ fn zirRetPtr( |
| 2076 | try sema.requireFunctionBlock(block, src); | 2078 | try sema.requireFunctionBlock(block, src); |
| 2077 | | 2079 | |
| 2078 | if (block.is_comptime) { | 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 | const ptr_type = try Type.ptr(sema.arena, .{ | 2085 | const ptr_type = try Type.ptr(sema.arena, .{ |
| ... | @@ -2227,7 +2230,7 @@ fn zirAllocExtended( | ... | @@ -2227,7 +2230,7 @@ fn zirAllocExtended( |
| 2227 | | 2230 | |
| 2228 | if (small.is_comptime) { | 2231 | if (small.is_comptime) { |
| 2229 | if (small.has_type) { | 2232 | if (small.has_type) { |
| 2230 | return sema.analyzeComptimeAlloc(block, var_ty, alignment); | 2233 | return sema.analyzeComptimeAlloc(block, var_ty, alignment, ty_src); |
| 2231 | } else { | 2234 | } else { |
| 2232 | return sema.addConstant( | 2235 | return sema.addConstant( |
| 2233 | inferred_alloc_ty, | 2236 | inferred_alloc_ty, |
| ... | @@ -2273,7 +2276,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -2273,7 +2276,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 2273 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 2276 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 2274 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; | 2277 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 2275 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); | 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 | fn zirAllocInferredComptime(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,7 +2298,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 2295 | const var_decl_src = inst_data.src(); | 2298 | const var_decl_src = inst_data.src(); |
| 2296 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); | 2299 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 2297 | if (block.is_comptime) { | 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 | const ptr_type = try Type.ptr(sema.arena, .{ | 2303 | const ptr_type = try Type.ptr(sema.arena, .{ |
| 2301 | .pointee_type = var_ty, | 2304 | .pointee_type = var_ty, |
| ... | @@ -2315,7 +2318,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -2315,7 +2318,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 2315 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; | 2318 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 2316 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); | 2319 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 2317 | if (block.is_comptime) { | 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 | try sema.validateVarType(block, ty_src, var_ty, false); | 2323 | try sema.validateVarType(block, ty_src, var_ty, false); |
| 2321 | const ptr_type = try Type.ptr(sema.arena, .{ | 2324 | const ptr_type = try Type.ptr(sema.arena, .{ |
| ... | @@ -4261,14 +4264,14 @@ fn analyzeCall( | ... | @@ -4261,14 +4264,14 @@ fn analyzeCall( |
| 4261 | const arg_src = call_src; // TODO: better source location | 4264 | const arg_src = call_src; // TODO: better source location |
| 4262 | if (i < fn_params_len) { | 4265 | if (i < fn_params_len) { |
| 4263 | const param_ty = func_ty.fnParamType(i); | 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 | args[i] = try sema.coerce(block, param_ty, uncasted_arg, arg_src); | 4268 | args[i] = try sema.coerce(block, param_ty, uncasted_arg, arg_src); |
| 4266 | } else { | 4269 | } else { |
| 4267 | args[i] = uncasted_arg; | 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 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + | 4276 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + |
| 4274 | args.len); | 4277 | args.len); |
| ... | @@ -4338,7 +4341,7 @@ fn finishGenericCall( | ... | @@ -4338,7 +4341,7 @@ fn finishGenericCall( |
| 4338 | const param_ty = new_fn_ty.fnParamType(runtime_i); | 4341 | const param_ty = new_fn_ty.fnParamType(runtime_i); |
| 4339 | const arg_src = call_src; // TODO: better source location | 4342 | const arg_src = call_src; // TODO: better source location |
| 4340 | const uncasted_arg = uncasted_args[total_i]; | 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 | const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); | 4345 | const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); |
| 4343 | runtime_args[runtime_i] = casted_arg; | 4346 | runtime_args[runtime_i] = casted_arg; |
| 4344 | runtime_i += 1; | 4347 | runtime_i += 1; |
| ... | @@ -4346,7 +4349,7 @@ fn finishGenericCall( | ... | @@ -4346,7 +4349,7 @@ fn finishGenericCall( |
| 4346 | total_i += 1; | 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 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + | 4354 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + |
| 4352 | runtime_args_len); | 4355 | runtime_args_len); |
| ... | @@ -8751,7 +8754,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -8751,7 +8754,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 8751 | .AnyFrame, | 8754 | .AnyFrame, |
| 8752 | => operand_ty.abiSize(target), | 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 | fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 8760 | fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -12429,7 +12432,7 @@ fn coerce( | ... | @@ -12429,7 +12432,7 @@ fn coerce( |
| 12429 | const arena = sema.arena; | 12432 | const arena = sema.arena; |
| 12430 | const target = sema.mod.getTarget(); | 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 | if (in_memory_result == .ok) { | 12436 | if (in_memory_result == .ok) { |
| 12434 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 12437 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 12435 | // Keep the comptime Value representation; take the new type. | 12438 | // Keep the comptime Value representation; take the new type. |
| ... | @@ -12482,7 +12485,7 @@ fn coerce( | ... | @@ -12482,7 +12485,7 @@ fn coerce( |
| 12482 | if (inst_ty.isConstPtr() and dest_is_mut) break :single_item; | 12485 | if (inst_ty.isConstPtr() and dest_is_mut) break :single_item; |
| 12483 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :single_item; | 12486 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :single_item; |
| 12484 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :single_item; | 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 | .ok => {}, | 12489 | .ok => {}, |
| 12487 | .no_match => break :single_item, | 12490 | .no_match => break :single_item, |
| 12488 | } | 12491 | } |
| ... | @@ -12494,14 +12497,16 @@ fn coerce( | ... | @@ -12494,14 +12497,16 @@ fn coerce( |
| 12494 | if (!inst_ty.isSinglePointer()) break :src_array_ptr; | 12497 | if (!inst_ty.isSinglePointer()) break :src_array_ptr; |
| 12495 | const array_ty = inst_ty.childType(); | 12498 | const array_ty = inst_ty.childType(); |
| 12496 | if (array_ty.zigTypeTag() != .Array) break :src_array_ptr; | 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 | const dest_is_mut = dest_info.mutable; | 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 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :src_array_ptr; | 12505 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :src_array_ptr; |
| 12501 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :src_array_ptr; | 12506 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :src_array_ptr; |
| 12502 | | 12507 | |
| 12503 | const dst_elem_type = dest_info.pointee_type; | 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 | .ok => {}, | 12510 | .ok => {}, |
| 12506 | .no_match => break :src_array_ptr, | 12511 | .no_match => break :src_array_ptr, |
| 12507 | } | 12512 | } |
| ... | @@ -12540,7 +12545,7 @@ fn coerce( | ... | @@ -12540,7 +12545,7 @@ fn coerce( |
| 12540 | const src_elem_ty = inst_ty.childType(); | 12545 | const src_elem_ty = inst_ty.childType(); |
| 12541 | const dest_is_mut = dest_info.mutable; | 12546 | const dest_is_mut = dest_info.mutable; |
| 12542 | const dst_elem_type = dest_info.pointee_type; | 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 | .ok => {}, | 12549 | .ok => {}, |
| 12545 | .no_match => break :src_c_ptr, | 12550 | .no_match => break :src_c_ptr, |
| 12546 | } | 12551 | } |
| ... | @@ -12738,10 +12743,13 @@ const InMemoryCoercionResult = enum { | ... | @@ -12738,10 +12743,13 @@ const InMemoryCoercionResult = enum { |
| 12738 | /// look at the function types_match_const_cast_only | 12743 | /// look at the function types_match_const_cast_only |
| 12739 | fn coerceInMemoryAllowed( | 12744 | fn coerceInMemoryAllowed( |
| 12740 | sema: *Sema, | 12745 | sema: *Sema, |
| | 12746 | block: *Block, |
| 12741 | dest_ty: Type, | 12747 | dest_ty: Type, |
| 12742 | src_ty: Type, | 12748 | src_ty: Type, |
| 12743 | dest_is_mut: bool, | 12749 | dest_is_mut: bool, |
| 12744 | target: std.Target, | 12750 | target: std.Target, |
| | 12751 | dest_src: LazySrcLoc, |
| | 12752 | src_src: LazySrcLoc, |
| 12745 | ) CompileError!InMemoryCoercionResult { | 12753 | ) CompileError!InMemoryCoercionResult { |
| 12746 | if (dest_ty.eql(src_ty)) | 12754 | if (dest_ty.eql(src_ty)) |
| 12747 | return .ok; | 12755 | return .ok; |
| ... | @@ -12749,15 +12757,15 @@ fn coerceInMemoryAllowed( | ... | @@ -12749,15 +12757,15 @@ fn coerceInMemoryAllowed( |
| 12749 | // Pointers / Pointer-like Optionals | 12757 | // Pointers / Pointer-like Optionals |
| 12750 | var dest_buf: Type.Payload.ElemType = undefined; | 12758 | var dest_buf: Type.Payload.ElemType = undefined; |
| 12751 | var src_buf: Type.Payload.ElemType = undefined; | 12759 | var src_buf: Type.Payload.ElemType = undefined; |
| 12752 | if (dest_ty.ptrOrOptionalPtrTy(&dest_buf)) |dest_ptr_ty| { | 12760 | if (try sema.typePtrOrOptionalPtrTy(block, dest_ty, &dest_buf, dest_src)) |dest_ptr_ty| { |
| 12753 | if (src_ty.ptrOrOptionalPtrTy(&src_buf)) |src_ptr_ty| { | 12761 | if (try sema.typePtrOrOptionalPtrTy(block, src_ty, &src_buf, src_src)) |src_ptr_ty| { |
| 12754 | return try sema.coerceInMemoryAllowedPtrs(dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut, target); | 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 | // Slices | 12766 | // Slices |
| 12759 | if (dest_ty.isSlice() and src_ty.isSlice()) { | 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 | const dest_tag = dest_ty.zigTypeTag(); | 12771 | const dest_tag = dest_ty.zigTypeTag(); |
| ... | @@ -12765,16 +12773,16 @@ fn coerceInMemoryAllowed( | ... | @@ -12765,16 +12773,16 @@ fn coerceInMemoryAllowed( |
| 12765 | | 12773 | |
| 12766 | // Functions | 12774 | // Functions |
| 12767 | if (dest_tag == .Fn and src_tag == .Fn) { | 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 | // Error Unions | 12779 | // Error Unions |
| 12772 | if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) { | 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 | if (child == .no_match) { | 12782 | if (child == .no_match) { |
| 12775 | return child; | 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 | // Error Sets | 12788 | // Error Sets |
| ... | @@ -12884,9 +12892,12 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -12884,9 +12892,12 @@ fn coerceInMemoryAllowedErrorSets( |
| 12884 | | 12892 | |
| 12885 | fn coerceInMemoryAllowedFns( | 12893 | fn coerceInMemoryAllowedFns( |
| 12886 | sema: *Sema, | 12894 | sema: *Sema, |
| | 12895 | block: *Block, |
| 12887 | dest_ty: Type, | 12896 | dest_ty: Type, |
| 12888 | src_ty: Type, | 12897 | src_ty: Type, |
| 12889 | target: std.Target, | 12898 | target: std.Target, |
| | 12899 | dest_src: LazySrcLoc, |
| | 12900 | src_src: LazySrcLoc, |
| 12890 | ) !InMemoryCoercionResult { | 12901 | ) !InMemoryCoercionResult { |
| 12891 | const dest_info = dest_ty.fnInfo(); | 12902 | const dest_info = dest_ty.fnInfo(); |
| 12892 | const src_info = src_ty.fnInfo(); | 12903 | const src_info = src_ty.fnInfo(); |
| ... | @@ -12900,7 +12911,7 @@ fn coerceInMemoryAllowedFns( | ... | @@ -12900,7 +12911,7 @@ fn coerceInMemoryAllowedFns( |
| 12900 | } | 12911 | } |
| 12901 | | 12912 | |
| 12902 | if (!src_info.return_type.isNoReturn()) { | 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 | if (rt == .no_match) { | 12915 | if (rt == .no_match) { |
| 12905 | return rt; | 12916 | return rt; |
| 12906 | } | 12917 | } |
| ... | @@ -12920,7 +12931,7 @@ fn coerceInMemoryAllowedFns( | ... | @@ -12920,7 +12931,7 @@ fn coerceInMemoryAllowedFns( |
| 12920 | // TODO: nolias | 12931 | // TODO: nolias |
| 12921 | | 12932 | |
| 12922 | // Note: Cast direction is reversed here. | 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 | if (param == .no_match) { | 12935 | if (param == .no_match) { |
| 12925 | return param; | 12936 | return param; |
| 12926 | } | 12937 | } |
| ... | @@ -12935,17 +12946,20 @@ fn coerceInMemoryAllowedFns( | ... | @@ -12935,17 +12946,20 @@ fn coerceInMemoryAllowedFns( |
| 12935 | | 12946 | |
| 12936 | fn coerceInMemoryAllowedPtrs( | 12947 | fn coerceInMemoryAllowedPtrs( |
| 12937 | sema: *Sema, | 12948 | sema: *Sema, |
| | 12949 | block: *Block, |
| 12938 | dest_ty: Type, | 12950 | dest_ty: Type, |
| 12939 | src_ty: Type, | 12951 | src_ty: Type, |
| 12940 | dest_ptr_ty: Type, | 12952 | dest_ptr_ty: Type, |
| 12941 | src_ptr_ty: Type, | 12953 | src_ptr_ty: Type, |
| 12942 | dest_is_mut: bool, | 12954 | dest_is_mut: bool, |
| 12943 | target: std.Target, | 12955 | target: std.Target, |
| | 12956 | dest_src: LazySrcLoc, |
| | 12957 | src_src: LazySrcLoc, |
| 12944 | ) !InMemoryCoercionResult { | 12958 | ) !InMemoryCoercionResult { |
| 12945 | const dest_info = dest_ptr_ty.ptrInfo().data; | 12959 | const dest_info = dest_ptr_ty.ptrInfo().data; |
| 12946 | const src_info = src_ptr_ty.ptrInfo().data; | 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 | if (child == .no_match) { | 12963 | if (child == .no_match) { |
| 12950 | return child; | 12964 | return child; |
| 12951 | } | 12965 | } |
| ... | @@ -13592,7 +13606,7 @@ fn coerceVectorInMemory( | ... | @@ -13592,7 +13606,7 @@ fn coerceVectorInMemory( |
| 13592 | const target = sema.mod.getTarget(); | 13606 | const target = sema.mod.getTarget(); |
| 13593 | const dest_elem_ty = dest_ty.childType(); | 13607 | const dest_elem_ty = dest_ty.childType(); |
| 13594 | const inst_elem_ty = inst_ty.childType(); | 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 | if (in_memory_result != .ok) { | 13610 | if (in_memory_result != .ok) { |
| 13597 | // TODO recursive error notes for coerceInMemoryAllowed failure | 13611 | // TODO recursive error notes for coerceInMemoryAllowed failure |
| 13598 | return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_ty, inst_ty }); | 13612 | return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_ty, inst_ty }); |
| ... | @@ -14351,12 +14365,12 @@ fn resolvePeerTypes( | ... | @@ -14351,12 +14365,12 @@ fn resolvePeerTypes( |
| 14351 | .Optional => { | 14365 | .Optional => { |
| 14352 | var opt_child_buf: Type.Payload.ElemType = undefined; | 14366 | var opt_child_buf: Type.Payload.ElemType = undefined; |
| 14353 | const opt_child_ty = candidate_ty.optionalChild(&opt_child_buf); | 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 | chosen = candidate; | 14369 | chosen = candidate; |
| 14356 | chosen_i = candidate_i + 1; | 14370 | chosen_i = candidate_i + 1; |
| 14357 | continue; | 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 | any_are_null = true; | 14374 | any_are_null = true; |
| 14361 | continue; | 14375 | continue; |
| 14362 | } | 14376 | } |
| ... | @@ -14379,10 +14393,10 @@ fn resolvePeerTypes( | ... | @@ -14379,10 +14393,10 @@ fn resolvePeerTypes( |
| 14379 | .Optional => { | 14393 | .Optional => { |
| 14380 | var opt_child_buf: Type.Payload.ElemType = undefined; | 14394 | var opt_child_buf: Type.Payload.ElemType = undefined; |
| 14381 | const opt_child_ty = chosen_ty.optionalChild(&opt_child_buf); | 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 | continue; | 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 | any_are_null = true; | 14400 | any_are_null = true; |
| 14387 | chosen = candidate; | 14401 | chosen = candidate; |
| 14388 | chosen_i = candidate_i + 1; | 14402 | chosen_i = candidate_i + 1; |
| ... | @@ -14439,38 +14453,8 @@ pub fn resolveTypeLayout( | ... | @@ -14439,38 +14453,8 @@ pub fn resolveTypeLayout( |
| 14439 | ty: Type, | 14453 | ty: Type, |
| 14440 | ) CompileError!void { | 14454 | ) CompileError!void { |
| 14441 | switch (ty.zigTypeTag()) { | 14455 | switch (ty.zigTypeTag()) { |
| 14442 | .Struct => { | 14456 | .Struct => return sema.resolveStructLayout(block, src, ty), |
| 14443 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); | 14457 | .Union => return sema.resolveUnionLayout(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 | }, | | |
| 14474 | .Array => { | 14458 | .Array => { |
| 14475 | const elem_ty = ty.childType(); | 14459 | const elem_ty = ty.childType(); |
| 14476 | return sema.resolveTypeLayout(block, src, elem_ty); | 14460 | return sema.resolveTypeLayout(block, src, elem_ty); |
| ... | @@ -14488,6 +14472,73 @@ pub fn resolveTypeLayout( | ... | @@ -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 | fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type { | 14542 | fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type { |
| 14492 | switch (ty.tag()) { | 14543 | switch (ty.tag()) { |
| 14493 | .@"struct" => { | 14544 | .@"struct" => { |
| ... | @@ -15215,11 +15266,20 @@ fn typeHasOnePossibleValue( | ... | @@ -15215,11 +15266,20 @@ fn typeHasOnePossibleValue( |
| 15215 | return null; | 15266 | return null; |
| 15216 | } | 15267 | } |
| 15217 | }, | 15268 | }, |
| 15218 | .@"union" => { | 15269 | .@"union", .union_tagged => { |
| 15219 | return null; // TODO | 15270 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 15220 | }, | 15271 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |
| 15221 | .union_tagged => { | 15272 | const tag_val = (try sema.typeHasOnePossibleValue(block, src, union_obj.tag_ty)) orelse |
| 15222 | return null; // TODO | 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 | .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), | 15285 | .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), |
| ... | @@ -15453,7 +15513,11 @@ fn analyzeComptimeAlloc( | ... | @@ -15453,7 +15513,11 @@ fn analyzeComptimeAlloc( |
| 15453 | block: *Block, | 15513 | block: *Block, |
| 15454 | var_type: Type, | 15514 | var_type: Type, |
| 15455 | alignment: u32, | 15515 | alignment: u32, |
| | 15516 | src: LazySrcLoc, |
| 15456 | ) CompileError!Air.Inst.Ref { | 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 | const ptr_type = try Type.ptr(sema.arena, .{ | 15521 | const ptr_type = try Type.ptr(sema.arena, .{ |
| 15458 | .pointee_type = var_type, | 15522 | .pointee_type = var_type, |
| 15459 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), | 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,8 +15615,8 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 15551 | // We have a Value that lines up in virtual memory exactly with what we want to load. | 15615 | // We have a Value that lines up in virtual memory exactly with what we want to load. |
| 15552 | // If the Type is in-memory coercable to `load_ty`, it may be returned without modifications. | 15616 | // If the Type is in-memory coercable to `load_ty`, it may be returned without modifications. |
| 15553 | const coerce_in_mem_ok = | 15617 | const coerce_in_mem_ok = |
| 15554 | (try sema.coerceInMemoryAllowed(load_ty, parent.ty, false, target)) == .ok or | 15618 | (try sema.coerceInMemoryAllowed(block, load_ty, parent.ty, false, target, src, src)) == .ok or |
| 15555 | (try sema.coerceInMemoryAllowed(parent.ty, load_ty, false, target)) == .ok; | 15619 | (try sema.coerceInMemoryAllowed(block, parent.ty, load_ty, false, target, src, src)) == .ok; |
| 15556 | if (coerce_in_mem_ok) { | 15620 | if (coerce_in_mem_ok) { |
| 15557 | if (parent.is_mutable) { | 15621 | if (parent.is_mutable) { |
| 15558 | // The decl whose value we are obtaining here may be overwritten with | 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,3 +15652,64 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError |
| 15588 | error.Overflow => return sema.fail(block, src, "expression produces integer value {d} which is too big for this compiler implementation to handle", .{int}), | 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 | } |