| ... | ... | @@ -1026,7 +1026,9 @@ fn resolveConstString( |
| 1026 | 1026 | |
| 1027 | 1027 | pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { |
| 1028 | 1028 | const air_inst = sema.resolveInst(zir_ref); |
| 1029 | | return sema.analyzeAsType(block, src, air_inst); |
| 1029 | const ty = try sema.analyzeAsType(block, src, air_inst); |
| 1030 | if (ty.tag() == .generic_poison) return error.GenericPoison; |
| 1031 | return ty; |
| 1030 | 1032 | } |
| 1031 | 1033 | |
| 1032 | 1034 | fn analyzeAsType( |
| ... | ... | @@ -1284,10 +1286,10 @@ fn resolveInt( |
| 1284 | 1286 | block: *Block, |
| 1285 | 1287 | src: LazySrcLoc, |
| 1286 | 1288 | zir_ref: Zir.Inst.Ref, |
| 1287 | | dest_type: Type, |
| 1289 | dest_ty: Type, |
| 1288 | 1290 | ) !u64 { |
| 1289 | 1291 | const air_inst = sema.resolveInst(zir_ref); |
| 1290 | | const coerced = try sema.coerce(block, dest_type, air_inst, src); |
| 1292 | const coerced = try sema.coerce(block, dest_ty, air_inst, src); |
| 1291 | 1293 | const val = try sema.resolveConstValue(block, src, coerced); |
| 1292 | 1294 | |
| 1293 | 1295 | return val.toUnsignedInt(); |
| ... | ... | @@ -2403,6 +2405,19 @@ fn failWithBadUnionFieldAccess( |
| 2403 | 2405 | return sema.failWithOwnedErrorMsg(msg); |
| 2404 | 2406 | } |
| 2405 | 2407 | |
| 2408 | fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void { |
| 2409 | const src_loc = decl_ty.declSrcLocOrNull() orelse return; |
| 2410 | const category = switch (decl_ty.zigTypeTag()) { |
| 2411 | .Union => "union", |
| 2412 | .Struct => "struct", |
| 2413 | .Enum => "enum", |
| 2414 | .Opaque => "opaque", |
| 2415 | .ErrorSet => "error set", |
| 2416 | else => unreachable, |
| 2417 | }; |
| 2418 | try sema.mod.errNoteNonLazy(src_loc, parent, "{s} declared here", .{category}); |
| 2419 | } |
| 2420 | |
| 2406 | 2421 | fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 2407 | 2422 | const tracy = trace(@src()); |
| 2408 | 2423 | defer tracy.end(); |
| ... | ... | @@ -5059,9 +5074,9 @@ fn analyzeAs( |
| 5059 | 5074 | zir_dest_type: Zir.Inst.Ref, |
| 5060 | 5075 | zir_operand: Zir.Inst.Ref, |
| 5061 | 5076 | ) CompileError!Air.Inst.Ref { |
| 5062 | | const dest_type = try sema.resolveType(block, src, zir_dest_type); |
| 5077 | const dest_ty = try sema.resolveType(block, src, zir_dest_type); |
| 5063 | 5078 | const operand = sema.resolveInst(zir_operand); |
| 5064 | | return sema.coerce(block, dest_type, operand, src); |
| 5079 | return sema.coerce(block, dest_ty, operand, src); |
| 5065 | 5080 | } |
| 5066 | 5081 | |
| 5067 | 5082 | fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5175,21 +5190,21 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 5175 | 5190 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 5176 | 5191 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 5177 | 5192 | |
| 5178 | | const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 5193 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 5179 | 5194 | const operand = sema.resolveInst(extra.rhs); |
| 5180 | 5195 | |
| 5181 | | const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_type); |
| 5196 | const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_ty); |
| 5182 | 5197 | _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand)); |
| 5183 | 5198 | |
| 5184 | 5199 | if (try sema.isComptimeKnown(block, operand_src, operand)) { |
| 5185 | | return sema.coerce(block, dest_type, operand, operand_src); |
| 5200 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 5186 | 5201 | } else if (dest_is_comptime_int) { |
| 5187 | 5202 | return sema.fail(block, src, "unable to cast runtime value to 'comptime_int'", .{}); |
| 5188 | 5203 | } |
| 5189 | 5204 | |
| 5190 | 5205 | try sema.requireRuntimeBlock(block, operand_src); |
| 5191 | 5206 | // TODO insert safety check to make sure the value fits in the dest type |
| 5192 | | return block.addTyOp(.intcast, dest_type, operand); |
| 5207 | return block.addTyOp(.intcast, dest_ty, operand); |
| 5193 | 5208 | } |
| 5194 | 5209 | |
| 5195 | 5210 | fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5201,9 +5216,9 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 5201 | 5216 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 5202 | 5217 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 5203 | 5218 | |
| 5204 | | const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 5219 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 5205 | 5220 | const operand = sema.resolveInst(extra.rhs); |
| 5206 | | return sema.bitCast(block, dest_type, operand, operand_src); |
| 5221 | return sema.bitCast(block, dest_ty, operand, operand_src); |
| 5207 | 5222 | } |
| 5208 | 5223 | |
| 5209 | 5224 | fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5216,17 +5231,17 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5216 | 5231 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 5217 | 5232 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 5218 | 5233 | |
| 5219 | | const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 5234 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 5220 | 5235 | const operand = sema.resolveInst(extra.rhs); |
| 5221 | 5236 | |
| 5222 | | const dest_is_comptime_float = switch (dest_type.zigTypeTag()) { |
| 5237 | const dest_is_comptime_float = switch (dest_ty.zigTypeTag()) { |
| 5223 | 5238 | .ComptimeFloat => true, |
| 5224 | 5239 | .Float => false, |
| 5225 | 5240 | else => return sema.fail( |
| 5226 | 5241 | block, |
| 5227 | 5242 | dest_ty_src, |
| 5228 | 5243 | "expected float type, found '{}'", |
| 5229 | | .{dest_type}, |
| 5244 | .{dest_ty}, |
| 5230 | 5245 | ), |
| 5231 | 5246 | }; |
| 5232 | 5247 | |
| ... | ... | @@ -5242,19 +5257,19 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5242 | 5257 | } |
| 5243 | 5258 | |
| 5244 | 5259 | if (try sema.isComptimeKnown(block, operand_src, operand)) { |
| 5245 | | return sema.coerce(block, dest_type, operand, operand_src); |
| 5260 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 5246 | 5261 | } |
| 5247 | 5262 | if (dest_is_comptime_float) { |
| 5248 | 5263 | return sema.fail(block, src, "unable to cast runtime value to 'comptime_float'", .{}); |
| 5249 | 5264 | } |
| 5250 | 5265 | const target = sema.mod.getTarget(); |
| 5251 | 5266 | const src_bits = operand_ty.floatBits(target); |
| 5252 | | const dst_bits = dest_type.floatBits(target); |
| 5267 | const dst_bits = dest_ty.floatBits(target); |
| 5253 | 5268 | if (dst_bits >= src_bits) { |
| 5254 | | return sema.coerce(block, dest_type, operand, operand_src); |
| 5269 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 5255 | 5270 | } |
| 5256 | 5271 | try sema.requireRuntimeBlock(block, operand_src); |
| 5257 | | return block.addTyOp(.fptrunc, dest_type, operand); |
| 5272 | return block.addTyOp(.fptrunc, dest_ty, operand); |
| 5258 | 5273 | } |
| 5259 | 5274 | |
| 5260 | 5275 | fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -11265,60 +11280,60 @@ fn elemPtrArray( |
| 11265 | 11280 | fn coerce( |
| 11266 | 11281 | sema: *Sema, |
| 11267 | 11282 | block: *Block, |
| 11268 | | dest_type_unresolved: Type, |
| 11283 | dest_ty_unresolved: Type, |
| 11269 | 11284 | inst: Air.Inst.Ref, |
| 11270 | 11285 | inst_src: LazySrcLoc, |
| 11271 | 11286 | ) CompileError!Air.Inst.Ref { |
| 11272 | | switch (dest_type_unresolved.tag()) { |
| 11287 | switch (dest_ty_unresolved.tag()) { |
| 11273 | 11288 | .var_args_param => return sema.coerceVarArgParam(block, inst, inst_src), |
| 11274 | 11289 | .generic_poison => return inst, |
| 11275 | 11290 | else => {}, |
| 11276 | 11291 | } |
| 11277 | | const dest_type_src = inst_src; // TODO better source location |
| 11278 | | const dest_type = try sema.resolveTypeFields(block, dest_type_src, dest_type_unresolved); |
| 11292 | const dest_ty_src = inst_src; // TODO better source location |
| 11293 | const dest_ty = try sema.resolveTypeFields(block, dest_ty_src, dest_ty_unresolved); |
| 11279 | 11294 | |
| 11280 | 11295 | const inst_ty = sema.typeOf(inst); |
| 11281 | 11296 | // If the types are the same, we can return the operand. |
| 11282 | | if (dest_type.eql(inst_ty)) |
| 11297 | if (dest_ty.eql(inst_ty)) |
| 11283 | 11298 | return inst; |
| 11284 | 11299 | |
| 11285 | 11300 | const arena = sema.arena; |
| 11286 | 11301 | const target = sema.mod.getTarget(); |
| 11287 | 11302 | |
| 11288 | | const in_memory_result = coerceInMemoryAllowed(dest_type, inst_ty, false, target); |
| 11303 | const in_memory_result = coerceInMemoryAllowed(dest_ty, inst_ty, false, target); |
| 11289 | 11304 | if (in_memory_result == .ok) { |
| 11290 | 11305 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 11291 | 11306 | // Keep the comptime Value representation; take the new type. |
| 11292 | | return sema.addConstant(dest_type, val); |
| 11307 | return sema.addConstant(dest_ty, val); |
| 11293 | 11308 | } |
| 11294 | 11309 | try sema.requireRuntimeBlock(block, inst_src); |
| 11295 | | return block.addTyOp(.bitcast, dest_type, inst); |
| 11310 | return block.addTyOp(.bitcast, dest_ty, inst); |
| 11296 | 11311 | } |
| 11297 | 11312 | |
| 11298 | 11313 | // undefined to anything |
| 11299 | 11314 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 11300 | 11315 | if (val.isUndef() or inst_ty.zigTypeTag() == .Undefined) { |
| 11301 | | return sema.addConstant(dest_type, val); |
| 11316 | return sema.addConstant(dest_ty, val); |
| 11302 | 11317 | } |
| 11303 | 11318 | } |
| 11304 | 11319 | assert(inst_ty.zigTypeTag() != .Undefined); |
| 11305 | 11320 | |
| 11306 | 11321 | // comptime known number to other number |
| 11307 | | if (try sema.coerceNum(block, dest_type, inst, inst_src)) |some| |
| 11322 | if (try sema.coerceNum(block, dest_ty, inst, inst_src)) |some| |
| 11308 | 11323 | return some; |
| 11309 | 11324 | |
| 11310 | | switch (dest_type.zigTypeTag()) { |
| 11325 | switch (dest_ty.zigTypeTag()) { |
| 11311 | 11326 | .Optional => { |
| 11312 | 11327 | // null to ?T |
| 11313 | 11328 | if (inst_ty.zigTypeTag() == .Null) { |
| 11314 | | return sema.addConstant(dest_type, Value.initTag(.null_value)); |
| 11329 | return sema.addConstant(dest_ty, Value.initTag(.null_value)); |
| 11315 | 11330 | } |
| 11316 | 11331 | |
| 11317 | 11332 | // T to ?T |
| 11318 | 11333 | var buf: Type.Payload.ElemType = undefined; |
| 11319 | | const child_type = dest_type.optionalChild(&buf); |
| 11334 | const child_type = dest_ty.optionalChild(&buf); |
| 11320 | 11335 | const intermediate = try sema.coerce(block, child_type, inst, inst_src); |
| 11321 | | return sema.wrapOptional(block, dest_type, intermediate, inst_src); |
| 11336 | return sema.wrapOptional(block, dest_ty, intermediate, inst_src); |
| 11322 | 11337 | }, |
| 11323 | 11338 | .Pointer => { |
| 11324 | 11339 | // Function body to function pointer. |
| ... | ... | @@ -11326,7 +11341,7 @@ fn coerce( |
| 11326 | 11341 | const fn_val = try sema.resolveConstValue(block, inst_src, inst); |
| 11327 | 11342 | const fn_decl = fn_val.castTag(.function).?.data.owner_decl; |
| 11328 | 11343 | const inst_as_ptr = try sema.analyzeDeclRef(fn_decl); |
| 11329 | | return sema.coerce(block, dest_type, inst_as_ptr, inst_src); |
| 11344 | return sema.coerce(block, dest_ty, inst_as_ptr, inst_src); |
| 11330 | 11345 | } |
| 11331 | 11346 | |
| 11332 | 11347 | // Coercions where the source is a single pointer to an array. |
| ... | ... | @@ -11335,38 +11350,38 @@ fn coerce( |
| 11335 | 11350 | const array_type = inst_ty.elemType(); |
| 11336 | 11351 | if (array_type.zigTypeTag() != .Array) break :src_array_ptr; |
| 11337 | 11352 | const array_elem_type = array_type.elemType(); |
| 11338 | | const dest_is_mut = !dest_type.isConstPtr(); |
| 11353 | const dest_is_mut = !dest_ty.isConstPtr(); |
| 11339 | 11354 | if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr; |
| 11340 | | if (inst_ty.isVolatilePtr() and !dest_type.isVolatilePtr()) break :src_array_ptr; |
| 11341 | | if (inst_ty.ptrAddressSpace() != dest_type.ptrAddressSpace()) break :src_array_ptr; |
| 11355 | if (inst_ty.isVolatilePtr() and !dest_ty.isVolatilePtr()) break :src_array_ptr; |
| 11356 | if (inst_ty.ptrAddressSpace() != dest_ty.ptrAddressSpace()) break :src_array_ptr; |
| 11342 | 11357 | |
| 11343 | | const dst_elem_type = dest_type.elemType(); |
| 11358 | const dst_elem_type = dest_ty.elemType(); |
| 11344 | 11359 | switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, target)) { |
| 11345 | 11360 | .ok => {}, |
| 11346 | 11361 | .no_match => break :src_array_ptr, |
| 11347 | 11362 | } |
| 11348 | 11363 | |
| 11349 | | switch (dest_type.ptrSize()) { |
| 11364 | switch (dest_ty.ptrSize()) { |
| 11350 | 11365 | .Slice => { |
| 11351 | 11366 | // *[N]T to []T |
| 11352 | | return sema.coerceArrayPtrToSlice(block, dest_type, inst, inst_src); |
| 11367 | return sema.coerceArrayPtrToSlice(block, dest_ty, inst, inst_src); |
| 11353 | 11368 | }, |
| 11354 | 11369 | .C => { |
| 11355 | 11370 | // *[N]T to [*c]T |
| 11356 | | return sema.coerceArrayPtrToMany(block, dest_type, inst, inst_src); |
| 11371 | return sema.coerceArrayPtrToMany(block, dest_ty, inst, inst_src); |
| 11357 | 11372 | }, |
| 11358 | 11373 | .Many => { |
| 11359 | 11374 | // *[N]T to [*]T |
| 11360 | 11375 | // *[N:s]T to [*:s]T |
| 11361 | 11376 | // *[N:s]T to [*]T |
| 11362 | | if (dest_type.sentinel()) |dst_sentinel| { |
| 11377 | if (dest_ty.sentinel()) |dst_sentinel| { |
| 11363 | 11378 | if (array_type.sentinel()) |src_sentinel| { |
| 11364 | 11379 | if (src_sentinel.eql(dst_sentinel, dst_elem_type)) { |
| 11365 | | return sema.coerceArrayPtrToMany(block, dest_type, inst, inst_src); |
| 11380 | return sema.coerceArrayPtrToMany(block, dest_ty, inst, inst_src); |
| 11366 | 11381 | } |
| 11367 | 11382 | } |
| 11368 | 11383 | } else { |
| 11369 | | return sema.coerceArrayPtrToMany(block, dest_type, inst, inst_src); |
| 11384 | return sema.coerceArrayPtrToMany(block, dest_ty, inst, inst_src); |
| 11370 | 11385 | } |
| 11371 | 11386 | }, |
| 11372 | 11387 | .One => {}, |
| ... | ... | @@ -11378,14 +11393,14 @@ fn coerce( |
| 11378 | 11393 | if (inst_ty.zigTypeTag() == .Int) { |
| 11379 | 11394 | assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above |
| 11380 | 11395 | |
| 11381 | | const dst_info = dest_type.intInfo(target); |
| 11396 | const dst_info = dest_ty.intInfo(target); |
| 11382 | 11397 | const src_info = inst_ty.intInfo(target); |
| 11383 | 11398 | if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or |
| 11384 | 11399 | // small enough unsigned ints can get casted to large enough signed ints |
| 11385 | 11400 | (dst_info.signedness == .signed and dst_info.bits > src_info.bits)) |
| 11386 | 11401 | { |
| 11387 | 11402 | try sema.requireRuntimeBlock(block, inst_src); |
| 11388 | | return block.addTyOp(.intcast, dest_type, inst); |
| 11403 | return block.addTyOp(.intcast, dest_ty, inst); |
| 11389 | 11404 | } |
| 11390 | 11405 | } |
| 11391 | 11406 | }, |
| ... | ... | @@ -11395,10 +11410,10 @@ fn coerce( |
| 11395 | 11410 | assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above |
| 11396 | 11411 | |
| 11397 | 11412 | const src_bits = inst_ty.floatBits(target); |
| 11398 | | const dst_bits = dest_type.floatBits(target); |
| 11413 | const dst_bits = dest_ty.floatBits(target); |
| 11399 | 11414 | if (dst_bits >= src_bits) { |
| 11400 | 11415 | try sema.requireRuntimeBlock(block, inst_src); |
| 11401 | | return block.addTyOp(.fpext, dest_type, inst); |
| 11416 | return block.addTyOp(.fpext, dest_ty, inst); |
| 11402 | 11417 | } |
| 11403 | 11418 | } |
| 11404 | 11419 | }, |
| ... | ... | @@ -11407,7 +11422,7 @@ fn coerce( |
| 11407 | 11422 | // enum literal to enum |
| 11408 | 11423 | const val = try sema.resolveConstValue(block, inst_src, inst); |
| 11409 | 11424 | const bytes = val.castTag(.enum_literal).?.data; |
| 11410 | | const resolved_dest_type = try sema.resolveTypeFields(block, inst_src, dest_type); |
| 11425 | const resolved_dest_type = try sema.resolveTypeFields(block, inst_src, dest_ty); |
| 11411 | 11426 | const field_index = resolved_dest_type.enumFieldIndex(bytes) orelse { |
| 11412 | 11427 | const msg = msg: { |
| 11413 | 11428 | const msg = try sema.errMsg( |
| ... | ... | @@ -11435,20 +11450,24 @@ fn coerce( |
| 11435 | 11450 | .Union => blk: { |
| 11436 | 11451 | // union to its own tag type |
| 11437 | 11452 | const union_tag_ty = inst_ty.unionTagType() orelse break :blk; |
| 11438 | | if (union_tag_ty.eql(dest_type)) { |
| 11439 | | return sema.unionToTag(block, dest_type, inst, inst_src); |
| 11453 | if (union_tag_ty.eql(dest_ty)) { |
| 11454 | return sema.unionToTag(block, dest_ty, inst, inst_src); |
| 11440 | 11455 | } |
| 11441 | 11456 | }, |
| 11442 | 11457 | else => {}, |
| 11443 | 11458 | }, |
| 11444 | 11459 | .ErrorUnion => { |
| 11445 | 11460 | // T to E!T or E to E!T |
| 11446 | | return sema.wrapErrorUnion(block, dest_type, inst, inst_src); |
| 11461 | return sema.wrapErrorUnion(block, dest_ty, inst, inst_src); |
| 11462 | }, |
| 11463 | .Union => switch (inst_ty.zigTypeTag()) { |
| 11464 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), |
| 11465 | else => {}, |
| 11447 | 11466 | }, |
| 11448 | 11467 | else => {}, |
| 11449 | 11468 | } |
| 11450 | 11469 | |
| 11451 | | return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_type, inst_ty }); |
| 11470 | return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_ty, inst_ty }); |
| 11452 | 11471 | } |
| 11453 | 11472 | |
| 11454 | 11473 | const InMemoryCoercionResult = enum { |
| ... | ... | @@ -11467,14 +11486,14 @@ const InMemoryCoercionResult = enum { |
| 11467 | 11486 | /// * sentinel-terminated pointers can coerce into `[*]` |
| 11468 | 11487 | /// TODO improve this function to report recursive compile errors like it does in stage1. |
| 11469 | 11488 | /// look at the function types_match_const_cast_only |
| 11470 | | fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, target: std.Target) InMemoryCoercionResult { |
| 11471 | | if (dest_type.eql(src_type)) |
| 11489 | fn coerceInMemoryAllowed(dest_ty: Type, src_type: Type, dest_is_mut: bool, target: std.Target) InMemoryCoercionResult { |
| 11490 | if (dest_ty.eql(src_type)) |
| 11472 | 11491 | return .ok; |
| 11473 | 11492 | |
| 11474 | | if (dest_type.zigTypeTag() == .Pointer and |
| 11493 | if (dest_ty.zigTypeTag() == .Pointer and |
| 11475 | 11494 | src_type.zigTypeTag() == .Pointer) |
| 11476 | 11495 | { |
| 11477 | | const dest_info = dest_type.ptrInfo().data; |
| 11496 | const dest_info = dest_ty.ptrInfo().data; |
| 11478 | 11497 | const src_info = src_type.ptrInfo().data; |
| 11479 | 11498 | |
| 11480 | 11499 | const child = coerceInMemoryAllowed(dest_info.pointee_type, src_info.pointee_type, dest_info.mutable, target); |
| ... | ... | @@ -11514,7 +11533,7 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, tar |
| 11514 | 11533 | return .no_match; |
| 11515 | 11534 | } |
| 11516 | 11535 | |
| 11517 | | if (dest_type.hasCodeGenBits() != src_type.hasCodeGenBits()) { |
| 11536 | if (dest_ty.hasCodeGenBits() != src_type.hasCodeGenBits()) { |
| 11518 | 11537 | return .no_match; |
| 11519 | 11538 | } |
| 11520 | 11539 | |
| ... | ... | @@ -11532,7 +11551,7 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, tar |
| 11532 | 11551 | !dest_info.pointee_type.eql(src_info.pointee_type)) |
| 11533 | 11552 | { |
| 11534 | 11553 | const src_align = src_type.ptrAlignment(target); |
| 11535 | | const dest_align = dest_type.ptrAlignment(target); |
| 11554 | const dest_align = dest_ty.ptrAlignment(target); |
| 11536 | 11555 | |
| 11537 | 11556 | if (dest_align > src_align) { |
| 11538 | 11557 | return .no_match; |
| ... | ... | @@ -11550,14 +11569,14 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, tar |
| 11550 | 11569 | fn coerceNum( |
| 11551 | 11570 | sema: *Sema, |
| 11552 | 11571 | block: *Block, |
| 11553 | | dest_type: Type, |
| 11572 | dest_ty: Type, |
| 11554 | 11573 | inst: Air.Inst.Ref, |
| 11555 | 11574 | inst_src: LazySrcLoc, |
| 11556 | 11575 | ) CompileError!?Air.Inst.Ref { |
| 11557 | 11576 | const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse return null; |
| 11558 | 11577 | const inst_ty = sema.typeOf(inst); |
| 11559 | 11578 | const src_zig_tag = inst_ty.zigTypeTag(); |
| 11560 | | const dst_zig_tag = dest_type.zigTypeTag(); |
| 11579 | const dst_zig_tag = dest_ty.zigTypeTag(); |
| 11561 | 11580 | |
| 11562 | 11581 | const target = sema.mod.getTarget(); |
| 11563 | 11582 | |
| ... | ... | @@ -11565,37 +11584,37 @@ fn coerceNum( |
| 11565 | 11584 | .ComptimeInt, .Int => switch (src_zig_tag) { |
| 11566 | 11585 | .Float, .ComptimeFloat => { |
| 11567 | 11586 | if (val.floatHasFraction()) { |
| 11568 | | return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val, dest_type }); |
| 11587 | return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val, dest_ty }); |
| 11569 | 11588 | } |
| 11570 | 11589 | return sema.fail(block, inst_src, "TODO float to int", .{}); |
| 11571 | 11590 | }, |
| 11572 | 11591 | .Int, .ComptimeInt => { |
| 11573 | | if (!val.intFitsInType(dest_type, target)) { |
| 11574 | | return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_type, val }); |
| 11592 | if (!val.intFitsInType(dest_ty, target)) { |
| 11593 | return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty, val }); |
| 11575 | 11594 | } |
| 11576 | | return try sema.addConstant(dest_type, val); |
| 11595 | return try sema.addConstant(dest_ty, val); |
| 11577 | 11596 | }, |
| 11578 | 11597 | else => {}, |
| 11579 | 11598 | }, |
| 11580 | 11599 | .ComptimeFloat, .Float => switch (src_zig_tag) { |
| 11581 | 11600 | .ComptimeFloat => { |
| 11582 | | const result_val = try val.floatCast(sema.arena, dest_type); |
| 11583 | | return try sema.addConstant(dest_type, result_val); |
| 11601 | const result_val = try val.floatCast(sema.arena, dest_ty); |
| 11602 | return try sema.addConstant(dest_ty, result_val); |
| 11584 | 11603 | }, |
| 11585 | 11604 | .Float => { |
| 11586 | | const result_val = try val.floatCast(sema.arena, dest_type); |
| 11587 | | if (!val.eql(result_val, dest_type)) { |
| 11605 | const result_val = try val.floatCast(sema.arena, dest_ty); |
| 11606 | if (!val.eql(result_val, dest_ty)) { |
| 11588 | 11607 | return sema.fail( |
| 11589 | 11608 | block, |
| 11590 | 11609 | inst_src, |
| 11591 | 11610 | "type {} cannot represent float value {}", |
| 11592 | | .{ dest_type, val }, |
| 11611 | .{ dest_ty, val }, |
| 11593 | 11612 | ); |
| 11594 | 11613 | } |
| 11595 | | return try sema.addConstant(dest_type, result_val); |
| 11614 | return try sema.addConstant(dest_ty, result_val); |
| 11596 | 11615 | }, |
| 11597 | 11616 | .Int, .ComptimeInt => { |
| 11598 | | const result_val = try val.intToFloat(sema.arena, dest_type, target); |
| 11617 | const result_val = try val.intToFloat(sema.arena, dest_ty, target); |
| 11599 | 11618 | // TODO implement this compile error |
| 11600 | 11619 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); |
| 11601 | 11620 | //if (!int_again_val.eql(val, inst_ty)) { |
| ... | ... | @@ -11603,10 +11622,10 @@ fn coerceNum( |
| 11603 | 11622 | // block, |
| 11604 | 11623 | // inst_src, |
| 11605 | 11624 | // "type {} cannot represent integer value {}", |
| 11606 | | // .{ dest_type, val }, |
| 11625 | // .{ dest_ty, val }, |
| 11607 | 11626 | // ); |
| 11608 | 11627 | //} |
| 11609 | | return try sema.addConstant(dest_type, result_val); |
| 11628 | return try sema.addConstant(dest_ty, result_val); |
| 11610 | 11629 | }, |
| 11611 | 11630 | else => {}, |
| 11612 | 11631 | }, |
| ... | ... | @@ -11816,31 +11835,66 @@ fn beginComptimePtrMutation( |
| 11816 | 11835 | .field_ptr => { |
| 11817 | 11836 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 11818 | 11837 | var parent = try beginComptimePtrMutation(sema, block, src, field_ptr.container_ptr); |
| 11819 | | const field_ty = parent.ty.structFieldType(field_ptr.field_index); |
| 11838 | const field_index = @intCast(u32, field_ptr.field_index); |
| 11839 | const field_ty = parent.ty.structFieldType(field_index); |
| 11820 | 11840 | switch (parent.val.tag()) { |
| 11821 | 11841 | .undef => { |
| 11822 | | // A struct has been initialized to undefined at comptime and now we |
| 11842 | // A struct or union has been initialized to undefined at comptime and now we |
| 11823 | 11843 | // are for the first time setting a field. We must change the representation |
| 11824 | | // of the struct from `undef` to `struct`. |
| 11844 | // of the struct/union from `undef` to `struct`/`union`. |
| 11825 | 11845 | const arena = parent.beginArena(sema.gpa); |
| 11826 | 11846 | defer parent.finishArena(); |
| 11827 | 11847 | |
| 11828 | | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); |
| 11829 | | mem.set(Value, fields, Value.undef); |
| 11848 | switch (parent.ty.zigTypeTag()) { |
| 11849 | .Struct => { |
| 11850 | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); |
| 11851 | mem.set(Value, fields, Value.undef); |
| 11830 | 11852 | |
| 11831 | | parent.val.* = try Value.Tag.@"struct".create(arena, fields); |
| 11853 | parent.val.* = try Value.Tag.@"struct".create(arena, fields); |
| 11832 | 11854 | |
| 11833 | | return ComptimePtrMutationKit{ |
| 11834 | | .decl_ref_mut = parent.decl_ref_mut, |
| 11835 | | .val = &fields[field_ptr.field_index], |
| 11836 | | .ty = field_ty, |
| 11837 | | }; |
| 11855 | return ComptimePtrMutationKit{ |
| 11856 | .decl_ref_mut = parent.decl_ref_mut, |
| 11857 | .val = &fields[field_index], |
| 11858 | .ty = field_ty, |
| 11859 | }; |
| 11860 | }, |
| 11861 | .Union => { |
| 11862 | const payload = try arena.create(Value.Payload.Union); |
| 11863 | payload.* = .{ .data = .{ |
| 11864 | .tag = try Value.Tag.enum_field_index.create(arena, field_index), |
| 11865 | .val = Value.undef, |
| 11866 | } }; |
| 11867 | |
| 11868 | parent.val.* = Value.initPayload(&payload.base); |
| 11869 | |
| 11870 | return ComptimePtrMutationKit{ |
| 11871 | .decl_ref_mut = parent.decl_ref_mut, |
| 11872 | .val = &payload.data.val, |
| 11873 | .ty = field_ty, |
| 11874 | }; |
| 11875 | }, |
| 11876 | else => unreachable, |
| 11877 | } |
| 11838 | 11878 | }, |
| 11839 | 11879 | .@"struct" => return ComptimePtrMutationKit{ |
| 11840 | 11880 | .decl_ref_mut = parent.decl_ref_mut, |
| 11841 | | .val = &parent.val.castTag(.@"struct").?.data[field_ptr.field_index], |
| 11881 | .val = &parent.val.castTag(.@"struct").?.data[field_index], |
| 11842 | 11882 | .ty = field_ty, |
| 11843 | 11883 | }, |
| 11884 | .@"union" => { |
| 11885 | // We need to set the active field of the union. |
| 11886 | const arena = parent.beginArena(sema.gpa); |
| 11887 | defer parent.finishArena(); |
| 11888 | |
| 11889 | const payload = &parent.val.castTag(.@"union").?.data; |
| 11890 | payload.tag = try Value.Tag.enum_field_index.create(arena, field_index); |
| 11891 | |
| 11892 | return ComptimePtrMutationKit{ |
| 11893 | .decl_ref_mut = parent.decl_ref_mut, |
| 11894 | .val = &payload.val, |
| 11895 | .ty = field_ty, |
| 11896 | }; |
| 11897 | }, |
| 11844 | 11898 | |
| 11845 | 11899 | else => unreachable, |
| 11846 | 11900 | } |
| ... | ... | @@ -11855,7 +11909,7 @@ fn beginComptimePtrMutation( |
| 11855 | 11909 | fn bitCast( |
| 11856 | 11910 | sema: *Sema, |
| 11857 | 11911 | block: *Block, |
| 11858 | | dest_type: Type, |
| 11912 | dest_ty: Type, |
| 11859 | 11913 | inst: Air.Inst.Ref, |
| 11860 | 11914 | inst_src: LazySrcLoc, |
| 11861 | 11915 | ) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -11863,41 +11917,132 @@ fn bitCast( |
| 11863 | 11917 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 11864 | 11918 | const target = sema.mod.getTarget(); |
| 11865 | 11919 | const old_ty = sema.typeOf(inst); |
| 11866 | | const result_val = try val.bitCast(old_ty, dest_type, target, sema.gpa, sema.arena); |
| 11867 | | return sema.addConstant(dest_type, result_val); |
| 11920 | const result_val = try val.bitCast(old_ty, dest_ty, target, sema.gpa, sema.arena); |
| 11921 | return sema.addConstant(dest_ty, result_val); |
| 11868 | 11922 | } |
| 11869 | 11923 | try sema.requireRuntimeBlock(block, inst_src); |
| 11870 | | return block.addTyOp(.bitcast, dest_type, inst); |
| 11924 | return block.addTyOp(.bitcast, dest_ty, inst); |
| 11871 | 11925 | } |
| 11872 | 11926 | |
| 11873 | 11927 | fn coerceArrayPtrToSlice( |
| 11874 | 11928 | sema: *Sema, |
| 11875 | 11929 | block: *Block, |
| 11876 | | dest_type: Type, |
| 11930 | dest_ty: Type, |
| 11877 | 11931 | inst: Air.Inst.Ref, |
| 11878 | 11932 | inst_src: LazySrcLoc, |
| 11879 | 11933 | ) CompileError!Air.Inst.Ref { |
| 11880 | 11934 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 11881 | 11935 | // The comptime Value representation is compatible with both types. |
| 11882 | | return sema.addConstant(dest_type, val); |
| 11936 | return sema.addConstant(dest_ty, val); |
| 11883 | 11937 | } |
| 11884 | 11938 | try sema.requireRuntimeBlock(block, inst_src); |
| 11885 | | return block.addTyOp(.array_to_slice, dest_type, inst); |
| 11939 | return block.addTyOp(.array_to_slice, dest_ty, inst); |
| 11886 | 11940 | } |
| 11887 | 11941 | |
| 11888 | 11942 | fn coerceArrayPtrToMany( |
| 11889 | 11943 | sema: *Sema, |
| 11890 | 11944 | block: *Block, |
| 11891 | | dest_type: Type, |
| 11945 | dest_ty: Type, |
| 11892 | 11946 | inst: Air.Inst.Ref, |
| 11893 | 11947 | inst_src: LazySrcLoc, |
| 11894 | 11948 | ) !Air.Inst.Ref { |
| 11895 | 11949 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 11896 | 11950 | // The comptime Value representation is compatible with both types. |
| 11897 | | return sema.addConstant(dest_type, val); |
| 11951 | return sema.addConstant(dest_ty, val); |
| 11898 | 11952 | } |
| 11899 | 11953 | try sema.requireRuntimeBlock(block, inst_src); |
| 11900 | | return sema.bitCast(block, dest_type, inst, inst_src); |
| 11954 | return sema.bitCast(block, dest_ty, inst, inst_src); |
| 11955 | } |
| 11956 | |
| 11957 | fn coerceEnumToUnion( |
| 11958 | sema: *Sema, |
| 11959 | block: *Block, |
| 11960 | union_ty: Type, |
| 11961 | union_ty_src: LazySrcLoc, |
| 11962 | inst: Air.Inst.Ref, |
| 11963 | inst_src: LazySrcLoc, |
| 11964 | ) !Air.Inst.Ref { |
| 11965 | const inst_ty = sema.typeOf(inst); |
| 11966 | |
| 11967 | const tag_ty = union_ty.unionTagType() orelse { |
| 11968 | const msg = msg: { |
| 11969 | const msg = try sema.errMsg(block, inst_src, "expected {}, found {}", .{ |
| 11970 | union_ty, inst_ty, |
| 11971 | }); |
| 11972 | errdefer msg.destroy(sema.gpa); |
| 11973 | try sema.errNote(block, union_ty_src, msg, "cannot coerce enum to untagged union", .{}); |
| 11974 | try sema.addDeclaredHereNote(msg, union_ty); |
| 11975 | break :msg msg; |
| 11976 | }; |
| 11977 | return sema.failWithOwnedErrorMsg(msg); |
| 11978 | }; |
| 11979 | |
| 11980 | const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src); |
| 11981 | if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| { |
| 11982 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 11983 | const field_index = union_obj.tag_ty.enumTagFieldIndex(val) orelse { |
| 11984 | const msg = msg: { |
| 11985 | const msg = try sema.errMsg(block, inst_src, "union {} has no tag with value {}", .{ |
| 11986 | union_ty, val, |
| 11987 | }); |
| 11988 | errdefer msg.destroy(sema.gpa); |
| 11989 | try sema.addDeclaredHereNote(msg, union_ty); |
| 11990 | break :msg msg; |
| 11991 | }; |
| 11992 | return sema.failWithOwnedErrorMsg(msg); |
| 11993 | }; |
| 11994 | const field = union_obj.fields.values()[field_index]; |
| 11995 | const field_ty = try sema.resolveTypeFields(block, inst_src, field.ty); |
| 11996 | const opv = (try sema.typeHasOnePossibleValue(block, inst_src, field_ty)) orelse { |
| 11997 | // TODO resolve the field names and include in the error message, |
| 11998 | // also instead of 'union declared here' make it 'field "foo" declared here'. |
| 11999 | const msg = msg: { |
| 12000 | const msg = try sema.errMsg(block, inst_src, "coercion to union {} must initialize {} field", .{ |
| 12001 | union_ty, field_ty, |
| 12002 | }); |
| 12003 | errdefer msg.destroy(sema.gpa); |
| 12004 | try sema.addDeclaredHereNote(msg, union_ty); |
| 12005 | break :msg msg; |
| 12006 | }; |
| 12007 | return sema.failWithOwnedErrorMsg(msg); |
| 12008 | }; |
| 12009 | |
| 12010 | return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{ |
| 12011 | .tag = val, |
| 12012 | .val = opv, |
| 12013 | })); |
| 12014 | } |
| 12015 | |
| 12016 | try sema.requireRuntimeBlock(block, inst_src); |
| 12017 | |
| 12018 | if (tag_ty.isNonexhaustiveEnum()) { |
| 12019 | const msg = msg: { |
| 12020 | const msg = try sema.errMsg(block, inst_src, "runtime coercion to union {} from non-exhaustive enum", .{ |
| 12021 | union_ty, |
| 12022 | }); |
| 12023 | errdefer msg.destroy(sema.gpa); |
| 12024 | try sema.addDeclaredHereNote(msg, tag_ty); |
| 12025 | break :msg msg; |
| 12026 | }; |
| 12027 | return sema.failWithOwnedErrorMsg(msg); |
| 12028 | } |
| 12029 | |
| 12030 | // If the union has all fields 0 bits, the union value is just the enum value. |
| 12031 | if (union_ty.unionHasAllZeroBitFieldTypes()) { |
| 12032 | return block.addTyOp(.bitcast, union_ty, enum_tag); |
| 12033 | } |
| 12034 | |
| 12035 | // TODO resolve the field names and add a hint that says "field 'foo' has type 'bar'" |
| 12036 | // instead of the "union declared here" hint |
| 12037 | const msg = msg: { |
| 12038 | const msg = try sema.errMsg(block, inst_src, "runtime coercion to union {} which has non-void fields", .{ |
| 12039 | union_ty, |
| 12040 | }); |
| 12041 | errdefer msg.destroy(sema.gpa); |
| 12042 | try sema.addDeclaredHereNote(msg, union_ty); |
| 12043 | break :msg msg; |
| 12044 | }; |
| 12045 | return sema.failWithOwnedErrorMsg(msg); |
| 11901 | 12046 | } |
| 11902 | 12047 | |
| 11903 | 12048 | fn analyzeDeclVal( |
| ... | ... | @@ -12223,7 +12368,7 @@ fn cmpNumeric( |
| 12223 | 12368 | const target = sema.mod.getTarget(); |
| 12224 | 12369 | if (lhs_is_float and rhs_is_float) { |
| 12225 | 12370 | // Implicit cast the smaller one to the larger one. |
| 12226 | | const dest_type = x: { |
| 12371 | const dest_ty = x: { |
| 12227 | 12372 | if (lhs_ty_tag == .ComptimeFloat) { |
| 12228 | 12373 | break :x rhs_ty; |
| 12229 | 12374 | } else if (rhs_ty_tag == .ComptimeFloat) { |
| ... | ... | @@ -12235,8 +12380,8 @@ fn cmpNumeric( |
| 12235 | 12380 | break :x rhs_ty; |
| 12236 | 12381 | } |
| 12237 | 12382 | }; |
| 12238 | | const casted_lhs = try sema.coerce(block, dest_type, lhs, lhs_src); |
| 12239 | | const casted_rhs = try sema.coerce(block, dest_type, rhs, rhs_src); |
| 12383 | const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src); |
| 12384 | const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src); |
| 12240 | 12385 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs); |
| 12241 | 12386 | } |
| 12242 | 12387 | // For mixed unsigned integer sizes, implicit cast both operands to the larger integer. |
| ... | ... | @@ -12327,7 +12472,7 @@ fn cmpNumeric( |
| 12327 | 12472 | rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed); |
| 12328 | 12473 | } |
| 12329 | 12474 | |
| 12330 | | const dest_type = if (dest_float_type) |ft| ft else blk: { |
| 12475 | const dest_ty = if (dest_float_type) |ft| ft else blk: { |
| 12331 | 12476 | const max_bits = std.math.max(lhs_bits, rhs_bits); |
| 12332 | 12477 | const casted_bits = std.math.cast(u16, max_bits) catch |err| switch (err) { |
| 12333 | 12478 | error.Overflow => return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits}), |
| ... | ... | @@ -12335,8 +12480,8 @@ fn cmpNumeric( |
| 12335 | 12480 | const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned; |
| 12336 | 12481 | break :blk try Module.makeIntType(sema.arena, signedness, casted_bits); |
| 12337 | 12482 | }; |
| 12338 | | const casted_lhs = try sema.coerce(block, dest_type, lhs, lhs_src); |
| 12339 | | const casted_rhs = try sema.coerce(block, dest_type, rhs, rhs_src); |
| 12483 | const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src); |
| 12484 | const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src); |
| 12340 | 12485 | |
| 12341 | 12486 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs); |
| 12342 | 12487 | } |
| ... | ... | @@ -12344,32 +12489,32 @@ fn cmpNumeric( |
| 12344 | 12489 | fn wrapOptional( |
| 12345 | 12490 | sema: *Sema, |
| 12346 | 12491 | block: *Block, |
| 12347 | | dest_type: Type, |
| 12492 | dest_ty: Type, |
| 12348 | 12493 | inst: Air.Inst.Ref, |
| 12349 | 12494 | inst_src: LazySrcLoc, |
| 12350 | 12495 | ) !Air.Inst.Ref { |
| 12351 | 12496 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 12352 | | return sema.addConstant(dest_type, try Value.Tag.opt_payload.create(sema.arena, val)); |
| 12497 | return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, val)); |
| 12353 | 12498 | } |
| 12354 | 12499 | |
| 12355 | 12500 | try sema.requireRuntimeBlock(block, inst_src); |
| 12356 | | return block.addTyOp(.wrap_optional, dest_type, inst); |
| 12501 | return block.addTyOp(.wrap_optional, dest_ty, inst); |
| 12357 | 12502 | } |
| 12358 | 12503 | |
| 12359 | 12504 | fn wrapErrorUnion( |
| 12360 | 12505 | sema: *Sema, |
| 12361 | 12506 | block: *Block, |
| 12362 | | dest_type: Type, |
| 12507 | dest_ty: Type, |
| 12363 | 12508 | inst: Air.Inst.Ref, |
| 12364 | 12509 | inst_src: LazySrcLoc, |
| 12365 | 12510 | ) !Air.Inst.Ref { |
| 12366 | 12511 | const inst_ty = sema.typeOf(inst); |
| 12367 | | const dest_err_set_ty = dest_type.errorUnionSet(); |
| 12368 | | const dest_payload_ty = dest_type.errorUnionPayload(); |
| 12512 | const dest_err_set_ty = dest_ty.errorUnionSet(); |
| 12513 | const dest_payload_ty = dest_ty.errorUnionPayload(); |
| 12369 | 12514 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 12370 | 12515 | if (inst_ty.zigTypeTag() != .ErrorSet) { |
| 12371 | 12516 | _ = try sema.coerce(block, dest_payload_ty, inst, inst_src); |
| 12372 | | return sema.addConstant(dest_type, try Value.Tag.eu_payload.create(sema.arena, val)); |
| 12517 | return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val)); |
| 12373 | 12518 | } |
| 12374 | 12519 | switch (dest_err_set_ty.tag()) { |
| 12375 | 12520 | .anyerror => {}, |
| ... | ... | @@ -12417,7 +12562,7 @@ fn wrapErrorUnion( |
| 12417 | 12562 | }, |
| 12418 | 12563 | else => unreachable, |
| 12419 | 12564 | } |
| 12420 | | return sema.addConstant(dest_type, val); |
| 12565 | return sema.addConstant(dest_ty, val); |
| 12421 | 12566 | } |
| 12422 | 12567 | |
| 12423 | 12568 | try sema.requireRuntimeBlock(block, inst_src); |
| ... | ... | @@ -12425,25 +12570,25 @@ fn wrapErrorUnion( |
| 12425 | 12570 | // we are coercing from E to E!T |
| 12426 | 12571 | if (inst_ty.zigTypeTag() == .ErrorSet) { |
| 12427 | 12572 | var coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src); |
| 12428 | | return block.addTyOp(.wrap_errunion_err, dest_type, coerced); |
| 12573 | return block.addTyOp(.wrap_errunion_err, dest_ty, coerced); |
| 12429 | 12574 | } else { |
| 12430 | 12575 | var coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src); |
| 12431 | | return block.addTyOp(.wrap_errunion_payload, dest_type, coerced); |
| 12576 | return block.addTyOp(.wrap_errunion_payload, dest_ty, coerced); |
| 12432 | 12577 | } |
| 12433 | 12578 | } |
| 12434 | 12579 | |
| 12435 | 12580 | fn unionToTag( |
| 12436 | 12581 | sema: *Sema, |
| 12437 | 12582 | block: *Block, |
| 12438 | | dest_type: Type, |
| 12583 | dest_ty: Type, |
| 12439 | 12584 | un: Air.Inst.Ref, |
| 12440 | 12585 | un_src: LazySrcLoc, |
| 12441 | 12586 | ) !Air.Inst.Ref { |
| 12442 | 12587 | if (try sema.resolveMaybeUndefVal(block, un_src, un)) |un_val| { |
| 12443 | | return sema.addConstant(dest_type, un_val.unionTag()); |
| 12588 | return sema.addConstant(dest_ty, un_val.unionTag()); |
| 12444 | 12589 | } |
| 12445 | 12590 | try sema.requireRuntimeBlock(block, un_src); |
| 12446 | | return block.addTyOp(.get_union_tag, dest_type, un); |
| 12591 | return block.addTyOp(.get_union_tag, dest_ty, un); |
| 12447 | 12592 | } |
| 12448 | 12593 | |
| 12449 | 12594 | fn resolvePeerTypes( |