| ... | @@ -1026,7 +1026,9 @@ fn resolveConstString( | ... | @@ -1026,7 +1026,9 @@ fn resolveConstString( |
| 1026 | | 1026 | |
| 1027 | pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { | 1027 | pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { |
| 1028 | const air_inst = sema.resolveInst(zir_ref); | 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 | fn analyzeAsType( | 1034 | fn analyzeAsType( |
| ... | @@ -1284,10 +1286,10 @@ fn resolveInt( | ... | @@ -1284,10 +1286,10 @@ fn resolveInt( |
| 1284 | block: *Block, | 1286 | block: *Block, |
| 1285 | src: LazySrcLoc, | 1287 | src: LazySrcLoc, |
| 1286 | zir_ref: Zir.Inst.Ref, | 1288 | zir_ref: Zir.Inst.Ref, |
| 1287 | dest_type: Type, | 1289 | dest_ty: Type, |
| 1288 | ) !u64 { | 1290 | ) !u64 { |
| 1289 | const air_inst = sema.resolveInst(zir_ref); | 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 | const val = try sema.resolveConstValue(block, src, coerced); | 1293 | const val = try sema.resolveConstValue(block, src, coerced); |
| 1292 | | 1294 | |
| 1293 | return val.toUnsignedInt(); | 1295 | return val.toUnsignedInt(); |
| ... | @@ -2403,6 +2405,19 @@ fn failWithBadUnionFieldAccess( | ... | @@ -2403,6 +2405,19 @@ fn failWithBadUnionFieldAccess( |
| 2403 | return sema.failWithOwnedErrorMsg(msg); | 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 | fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 2421 | fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 2407 | const tracy = trace(@src()); | 2422 | const tracy = trace(@src()); |
| 2408 | defer tracy.end(); | 2423 | defer tracy.end(); |
| ... | @@ -5059,9 +5074,9 @@ fn analyzeAs( | ... | @@ -5059,9 +5074,9 @@ fn analyzeAs( |
| 5059 | zir_dest_type: Zir.Inst.Ref, | 5074 | zir_dest_type: Zir.Inst.Ref, |
| 5060 | zir_operand: Zir.Inst.Ref, | 5075 | zir_operand: Zir.Inst.Ref, |
| 5061 | ) CompileError!Air.Inst.Ref { | 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 | const operand = sema.resolveInst(zir_operand); | 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 | fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,21 +5190,21 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 5175 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 5190 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 5176 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 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 | const operand = sema.resolveInst(extra.rhs); | 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 | _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand)); | 5197 | _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand)); |
| 5183 | | 5198 | |
| 5184 | if (try sema.isComptimeKnown(block, operand_src, operand)) { | 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 | } else if (dest_is_comptime_int) { | 5201 | } else if (dest_is_comptime_int) { |
| 5187 | return sema.fail(block, src, "unable to cast runtime value to 'comptime_int'", .{}); | 5202 | return sema.fail(block, src, "unable to cast runtime value to 'comptime_int'", .{}); |
| 5188 | } | 5203 | } |
| 5189 | | 5204 | |
| 5190 | try sema.requireRuntimeBlock(block, operand_src); | 5205 | try sema.requireRuntimeBlock(block, operand_src); |
| 5191 | // TODO insert safety check to make sure the value fits in the dest type | 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 | fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,9 +5216,9 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 5201 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 5216 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 5202 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 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 | const operand = sema.resolveInst(extra.rhs); | 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 | fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 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,17 +5231,17 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5216 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 5231 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 5217 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 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 | const operand = sema.resolveInst(extra.rhs); | 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 | .ComptimeFloat => true, | 5238 | .ComptimeFloat => true, |
| 5224 | .Float => false, | 5239 | .Float => false, |
| 5225 | else => return sema.fail( | 5240 | else => return sema.fail( |
| 5226 | block, | 5241 | block, |
| 5227 | dest_ty_src, | 5242 | dest_ty_src, |
| 5228 | "expected float type, found '{}'", | 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,19 +5257,19 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5242 | } | 5257 | } |
| 5243 | | 5258 | |
| 5244 | if (try sema.isComptimeKnown(block, operand_src, operand)) { | 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 | if (dest_is_comptime_float) { | 5262 | if (dest_is_comptime_float) { |
| 5248 | return sema.fail(block, src, "unable to cast runtime value to 'comptime_float'", .{}); | 5263 | return sema.fail(block, src, "unable to cast runtime value to 'comptime_float'", .{}); |
| 5249 | } | 5264 | } |
| 5250 | const target = sema.mod.getTarget(); | 5265 | const target = sema.mod.getTarget(); |
| 5251 | const src_bits = operand_ty.floatBits(target); | 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 | if (dst_bits >= src_bits) { | 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 | try sema.requireRuntimeBlock(block, operand_src); | 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 | fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 5275 | fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -11265,60 +11280,60 @@ fn elemPtrArray( | ... | @@ -11265,60 +11280,60 @@ fn elemPtrArray( |
| 11265 | fn coerce( | 11280 | fn coerce( |
| 11266 | sema: *Sema, | 11281 | sema: *Sema, |
| 11267 | block: *Block, | 11282 | block: *Block, |
| 11268 | dest_type_unresolved: Type, | 11283 | dest_ty_unresolved: Type, |
| 11269 | inst: Air.Inst.Ref, | 11284 | inst: Air.Inst.Ref, |
| 11270 | inst_src: LazySrcLoc, | 11285 | inst_src: LazySrcLoc, |
| 11271 | ) CompileError!Air.Inst.Ref { | 11286 | ) CompileError!Air.Inst.Ref { |
| 11272 | switch (dest_type_unresolved.tag()) { | 11287 | switch (dest_ty_unresolved.tag()) { |
| 11273 | .var_args_param => return sema.coerceVarArgParam(block, inst, inst_src), | 11288 | .var_args_param => return sema.coerceVarArgParam(block, inst, inst_src), |
| 11274 | .generic_poison => return inst, | 11289 | .generic_poison => return inst, |
| 11275 | else => {}, | 11290 | else => {}, |
| 11276 | } | 11291 | } |
| 11277 | const dest_type_src = inst_src; // TODO better source location | 11292 | const dest_ty_src = inst_src; // TODO better source location |
| 11278 | const dest_type = try sema.resolveTypeFields(block, dest_type_src, dest_type_unresolved); | 11293 | const dest_ty = try sema.resolveTypeFields(block, dest_ty_src, dest_ty_unresolved); |
| 11279 | | 11294 | |
| 11280 | const inst_ty = sema.typeOf(inst); | 11295 | const inst_ty = sema.typeOf(inst); |
| 11281 | // If the types are the same, we can return the operand. | 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 | return inst; | 11298 | return inst; |
| 11284 | | 11299 | |
| 11285 | const arena = sema.arena; | 11300 | const arena = sema.arena; |
| 11286 | const target = sema.mod.getTarget(); | 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 | if (in_memory_result == .ok) { | 11304 | if (in_memory_result == .ok) { |
| 11290 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 11305 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 11291 | // Keep the comptime Value representation; take the new type. | 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 | try sema.requireRuntimeBlock(block, inst_src); | 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 | // undefined to anything | 11313 | // undefined to anything |
| 11299 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 11314 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 11300 | if (val.isUndef() or inst_ty.zigTypeTag() == .Undefined) { | 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 | assert(inst_ty.zigTypeTag() != .Undefined); | 11319 | assert(inst_ty.zigTypeTag() != .Undefined); |
| 11305 | | 11320 | |
| 11306 | // comptime known number to other number | 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 | return some; | 11323 | return some; |
| 11309 | | 11324 | |
| 11310 | switch (dest_type.zigTypeTag()) { | 11325 | switch (dest_ty.zigTypeTag()) { |
| 11311 | .Optional => { | 11326 | .Optional => { |
| 11312 | // null to ?T | 11327 | // null to ?T |
| 11313 | if (inst_ty.zigTypeTag() == .Null) { | 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 | // T to ?T | 11332 | // T to ?T |
| 11318 | var buf: Type.Payload.ElemType = undefined; | 11333 | var buf: Type.Payload.ElemType = undefined; |
| 11319 | const child_type = dest_type.optionalChild(&buf); | 11334 | const child_type = dest_ty.optionalChild(&buf); |
| 11320 | const intermediate = try sema.coerce(block, child_type, inst, inst_src); | 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 | .Pointer => { | 11338 | .Pointer => { |
| 11324 | // Function body to function pointer. | 11339 | // Function body to function pointer. |
| ... | @@ -11326,7 +11341,7 @@ fn coerce( | ... | @@ -11326,7 +11341,7 @@ fn coerce( |
| 11326 | const fn_val = try sema.resolveConstValue(block, inst_src, inst); | 11341 | const fn_val = try sema.resolveConstValue(block, inst_src, inst); |
| 11327 | const fn_decl = fn_val.castTag(.function).?.data.owner_decl; | 11342 | const fn_decl = fn_val.castTag(.function).?.data.owner_decl; |
| 11328 | const inst_as_ptr = try sema.analyzeDeclRef(fn_decl); | 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 | // Coercions where the source is a single pointer to an array. | 11347 | // Coercions where the source is a single pointer to an array. |
| ... | @@ -11335,38 +11350,38 @@ fn coerce( | ... | @@ -11335,38 +11350,38 @@ fn coerce( |
| 11335 | const array_type = inst_ty.elemType(); | 11350 | const array_type = inst_ty.elemType(); |
| 11336 | if (array_type.zigTypeTag() != .Array) break :src_array_ptr; | 11351 | if (array_type.zigTypeTag() != .Array) break :src_array_ptr; |
| 11337 | const array_elem_type = array_type.elemType(); | 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 | if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr; | 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; | 11355 | if (inst_ty.isVolatilePtr() and !dest_ty.isVolatilePtr()) break :src_array_ptr; |
| 11341 | if (inst_ty.ptrAddressSpace() != dest_type.ptrAddressSpace()) 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 | switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, target)) { | 11359 | switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, target)) { |
| 11345 | .ok => {}, | 11360 | .ok => {}, |
| 11346 | .no_match => break :src_array_ptr, | 11361 | .no_match => break :src_array_ptr, |
| 11347 | } | 11362 | } |
| 11348 | | 11363 | |
| 11349 | switch (dest_type.ptrSize()) { | 11364 | switch (dest_ty.ptrSize()) { |
| 11350 | .Slice => { | 11365 | .Slice => { |
| 11351 | // *[N]T to []T | 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 | .C => { | 11369 | .C => { |
| 11355 | // *[N]T to [*c]T | 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 | .Many => { | 11373 | .Many => { |
| 11359 | // *[N]T to [*]T | 11374 | // *[N]T to [*]T |
| 11360 | // *[N:s]T to [*:s]T | 11375 | // *[N:s]T to [*:s]T |
| 11361 | // *[N:s]T to [*]T | 11376 | // *[N:s]T to [*]T |
| 11362 | if (dest_type.sentinel()) |dst_sentinel| { | 11377 | if (dest_ty.sentinel()) |dst_sentinel| { |
| 11363 | if (array_type.sentinel()) |src_sentinel| { | 11378 | if (array_type.sentinel()) |src_sentinel| { |
| 11364 | if (src_sentinel.eql(dst_sentinel, dst_elem_type)) { | 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 | } else { | 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 | .One => {}, | 11387 | .One => {}, |
| ... | @@ -11378,14 +11393,14 @@ fn coerce( | ... | @@ -11378,14 +11393,14 @@ fn coerce( |
| 11378 | if (inst_ty.zigTypeTag() == .Int) { | 11393 | if (inst_ty.zigTypeTag() == .Int) { |
| 11379 | assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above | 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 | const src_info = inst_ty.intInfo(target); | 11397 | const src_info = inst_ty.intInfo(target); |
| 11383 | if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or | 11398 | if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or |
| 11384 | // small enough unsigned ints can get casted to large enough signed ints | 11399 | // small enough unsigned ints can get casted to large enough signed ints |
| 11385 | (dst_info.signedness == .signed and dst_info.bits > src_info.bits)) | 11400 | (dst_info.signedness == .signed and dst_info.bits > src_info.bits)) |
| 11386 | { | 11401 | { |
| 11387 | try sema.requireRuntimeBlock(block, inst_src); | 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,10 +11410,10 @@ fn coerce( |
| 11395 | assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above | 11410 | assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above |
| 11396 | | 11411 | |
| 11397 | const src_bits = inst_ty.floatBits(target); | 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 | if (dst_bits >= src_bits) { | 11414 | if (dst_bits >= src_bits) { |
| 11400 | try sema.requireRuntimeBlock(block, inst_src); | 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,7 +11422,7 @@ fn coerce( |
| 11407 | // enum literal to enum | 11422 | // enum literal to enum |
| 11408 | const val = try sema.resolveConstValue(block, inst_src, inst); | 11423 | const val = try sema.resolveConstValue(block, inst_src, inst); |
| 11409 | const bytes = val.castTag(.enum_literal).?.data; | 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 | const field_index = resolved_dest_type.enumFieldIndex(bytes) orelse { | 11426 | const field_index = resolved_dest_type.enumFieldIndex(bytes) orelse { |
| 11412 | const msg = msg: { | 11427 | const msg = msg: { |
| 11413 | const msg = try sema.errMsg( | 11428 | const msg = try sema.errMsg( |
| ... | @@ -11435,20 +11450,24 @@ fn coerce( | ... | @@ -11435,20 +11450,24 @@ fn coerce( |
| 11435 | .Union => blk: { | 11450 | .Union => blk: { |
| 11436 | // union to its own tag type | 11451 | // union to its own tag type |
| 11437 | const union_tag_ty = inst_ty.unionTagType() orelse break :blk; | 11452 | const union_tag_ty = inst_ty.unionTagType() orelse break :blk; |
| 11438 | if (union_tag_ty.eql(dest_type)) { | 11453 | if (union_tag_ty.eql(dest_ty)) { |
| 11439 | return sema.unionToTag(block, dest_type, inst, inst_src); | 11454 | return sema.unionToTag(block, dest_ty, inst, inst_src); |
| 11440 | } | 11455 | } |
| 11441 | }, | 11456 | }, |
| 11442 | else => {}, | 11457 | else => {}, |
| 11443 | }, | 11458 | }, |
| 11444 | .ErrorUnion => { | 11459 | .ErrorUnion => { |
| 11445 | // T to E!T or E to E!T | 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 | else => {}, | 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 | const InMemoryCoercionResult = enum { | 11473 | const InMemoryCoercionResult = enum { |
| ... | @@ -11467,14 +11486,14 @@ const InMemoryCoercionResult = enum { | ... | @@ -11467,14 +11486,14 @@ const InMemoryCoercionResult = enum { |
| 11467 | /// * sentinel-terminated pointers can coerce into `[*]` | 11486 | /// * sentinel-terminated pointers can coerce into `[*]` |
| 11468 | /// TODO improve this function to report recursive compile errors like it does in stage1. | 11487 | /// TODO improve this function to report recursive compile errors like it does in stage1. |
| 11469 | /// look at the function types_match_const_cast_only | 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 { | 11489 | fn coerceInMemoryAllowed(dest_ty: Type, src_type: Type, dest_is_mut: bool, target: std.Target) InMemoryCoercionResult { |
| 11471 | if (dest_type.eql(src_type)) | 11490 | if (dest_ty.eql(src_type)) |
| 11472 | return .ok; | 11491 | return .ok; |
| 11473 | | 11492 | |
| 11474 | if (dest_type.zigTypeTag() == .Pointer and | 11493 | if (dest_ty.zigTypeTag() == .Pointer and |
| 11475 | src_type.zigTypeTag() == .Pointer) | 11494 | src_type.zigTypeTag() == .Pointer) |
| 11476 | { | 11495 | { |
| 11477 | const dest_info = dest_type.ptrInfo().data; | 11496 | const dest_info = dest_ty.ptrInfo().data; |
| 11478 | const src_info = src_type.ptrInfo().data; | 11497 | const src_info = src_type.ptrInfo().data; |
| 11479 | | 11498 | |
| 11480 | const child = coerceInMemoryAllowed(dest_info.pointee_type, src_info.pointee_type, dest_info.mutable, target); | 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,7 +11533,7 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, tar |
| 11514 | return .no_match; | 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 | return .no_match; | 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,7 +11551,7 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, tar |
| 11532 | !dest_info.pointee_type.eql(src_info.pointee_type)) | 11551 | !dest_info.pointee_type.eql(src_info.pointee_type)) |
| 11533 | { | 11552 | { |
| 11534 | const src_align = src_type.ptrAlignment(target); | 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 | if (dest_align > src_align) { | 11556 | if (dest_align > src_align) { |
| 11538 | return .no_match; | 11557 | return .no_match; |
| ... | @@ -11550,14 +11569,14 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, tar | ... | @@ -11550,14 +11569,14 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, tar |
| 11550 | fn coerceNum( | 11569 | fn coerceNum( |
| 11551 | sema: *Sema, | 11570 | sema: *Sema, |
| 11552 | block: *Block, | 11571 | block: *Block, |
| 11553 | dest_type: Type, | 11572 | dest_ty: Type, |
| 11554 | inst: Air.Inst.Ref, | 11573 | inst: Air.Inst.Ref, |
| 11555 | inst_src: LazySrcLoc, | 11574 | inst_src: LazySrcLoc, |
| 11556 | ) CompileError!?Air.Inst.Ref { | 11575 | ) CompileError!?Air.Inst.Ref { |
| 11557 | const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse return null; | 11576 | const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse return null; |
| 11558 | const inst_ty = sema.typeOf(inst); | 11577 | const inst_ty = sema.typeOf(inst); |
| 11559 | const src_zig_tag = inst_ty.zigTypeTag(); | 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 | const target = sema.mod.getTarget(); | 11581 | const target = sema.mod.getTarget(); |
| 11563 | | 11582 | |
| ... | @@ -11565,37 +11584,37 @@ fn coerceNum( | ... | @@ -11565,37 +11584,37 @@ fn coerceNum( |
| 11565 | .ComptimeInt, .Int => switch (src_zig_tag) { | 11584 | .ComptimeInt, .Int => switch (src_zig_tag) { |
| 11566 | .Float, .ComptimeFloat => { | 11585 | .Float, .ComptimeFloat => { |
| 11567 | if (val.floatHasFraction()) { | 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 | return sema.fail(block, inst_src, "TODO float to int", .{}); | 11589 | return sema.fail(block, inst_src, "TODO float to int", .{}); |
| 11571 | }, | 11590 | }, |
| 11572 | .Int, .ComptimeInt => { | 11591 | .Int, .ComptimeInt => { |
| 11573 | if (!val.intFitsInType(dest_type, target)) { | 11592 | if (!val.intFitsInType(dest_ty, target)) { |
| 11574 | return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_type, val }); | 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 | else => {}, | 11597 | else => {}, |
| 11579 | }, | 11598 | }, |
| 11580 | .ComptimeFloat, .Float => switch (src_zig_tag) { | 11599 | .ComptimeFloat, .Float => switch (src_zig_tag) { |
| 11581 | .ComptimeFloat => { | 11600 | .ComptimeFloat => { |
| 11582 | const result_val = try val.floatCast(sema.arena, dest_type); | 11601 | const result_val = try val.floatCast(sema.arena, dest_ty); |
| 11583 | return try sema.addConstant(dest_type, result_val); | 11602 | return try sema.addConstant(dest_ty, result_val); |
| 11584 | }, | 11603 | }, |
| 11585 | .Float => { | 11604 | .Float => { |
| 11586 | const result_val = try val.floatCast(sema.arena, dest_type); | 11605 | const result_val = try val.floatCast(sema.arena, dest_ty); |
| 11587 | if (!val.eql(result_val, dest_type)) { | 11606 | if (!val.eql(result_val, dest_ty)) { |
| 11588 | return sema.fail( | 11607 | return sema.fail( |
| 11589 | block, | 11608 | block, |
| 11590 | inst_src, | 11609 | inst_src, |
| 11591 | "type {} cannot represent float value {}", | 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 | .Int, .ComptimeInt => { | 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 | // TODO implement this compile error | 11618 | // TODO implement this compile error |
| 11600 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); | 11619 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); |
| 11601 | //if (!int_again_val.eql(val, inst_ty)) { | 11620 | //if (!int_again_val.eql(val, inst_ty)) { |
| ... | @@ -11603,10 +11622,10 @@ fn coerceNum( | ... | @@ -11603,10 +11622,10 @@ fn coerceNum( |
| 11603 | // block, | 11622 | // block, |
| 11604 | // inst_src, | 11623 | // inst_src, |
| 11605 | // "type {} cannot represent integer value {}", | 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 | else => {}, | 11630 | else => {}, |
| 11612 | }, | 11631 | }, |
| ... | @@ -11816,31 +11835,66 @@ fn beginComptimePtrMutation( | ... | @@ -11816,31 +11835,66 @@ fn beginComptimePtrMutation( |
| 11816 | .field_ptr => { | 11835 | .field_ptr => { |
| 11817 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | 11836 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 11818 | var parent = try beginComptimePtrMutation(sema, block, src, field_ptr.container_ptr); | 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 | switch (parent.val.tag()) { | 11840 | switch (parent.val.tag()) { |
| 11821 | .undef => { | 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 | // are for the first time setting a field. We must change the representation | 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 | const arena = parent.beginArena(sema.gpa); | 11845 | const arena = parent.beginArena(sema.gpa); |
| 11826 | defer parent.finishArena(); | 11846 | defer parent.finishArena(); |
| 11827 | | 11847 | |
| 11828 | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); | 11848 | switch (parent.ty.zigTypeTag()) { |
| 11829 | mem.set(Value, fields, Value.undef); | 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{ | 11855 | return ComptimePtrMutationKit{ |
| 11834 | .decl_ref_mut = parent.decl_ref_mut, | 11856 | .decl_ref_mut = parent.decl_ref_mut, |
| 11835 | .val = &fields[field_ptr.field_index], | 11857 | .val = &fields[field_index], |
| 11836 | .ty = field_ty, | 11858 | .ty = field_ty, |
| 11837 | }; | 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 | .@"struct" => return ComptimePtrMutationKit{ | 11879 | .@"struct" => return ComptimePtrMutationKit{ |
| 11840 | .decl_ref_mut = parent.decl_ref_mut, | 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 | .ty = field_ty, | 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 | else => unreachable, | 11899 | else => unreachable, |
| 11846 | } | 11900 | } |
| ... | @@ -11855,7 +11909,7 @@ fn beginComptimePtrMutation( | ... | @@ -11855,7 +11909,7 @@ fn beginComptimePtrMutation( |
| 11855 | fn bitCast( | 11909 | fn bitCast( |
| 11856 | sema: *Sema, | 11910 | sema: *Sema, |
| 11857 | block: *Block, | 11911 | block: *Block, |
| 11858 | dest_type: Type, | 11912 | dest_ty: Type, |
| 11859 | inst: Air.Inst.Ref, | 11913 | inst: Air.Inst.Ref, |
| 11860 | inst_src: LazySrcLoc, | 11914 | inst_src: LazySrcLoc, |
| 11861 | ) CompileError!Air.Inst.Ref { | 11915 | ) CompileError!Air.Inst.Ref { |
| ... | @@ -11863,41 +11917,132 @@ fn bitCast( | ... | @@ -11863,41 +11917,132 @@ fn bitCast( |
| 11863 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 11917 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 11864 | const target = sema.mod.getTarget(); | 11918 | const target = sema.mod.getTarget(); |
| 11865 | const old_ty = sema.typeOf(inst); | 11919 | const old_ty = sema.typeOf(inst); |
| 11866 | const result_val = try val.bitCast(old_ty, dest_type, target, sema.gpa, sema.arena); | 11920 | const result_val = try val.bitCast(old_ty, dest_ty, target, sema.gpa, sema.arena); |
| 11867 | return sema.addConstant(dest_type, result_val); | 11921 | return sema.addConstant(dest_ty, result_val); |
| 11868 | } | 11922 | } |
| 11869 | try sema.requireRuntimeBlock(block, inst_src); | 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 | fn coerceArrayPtrToSlice( | 11927 | fn coerceArrayPtrToSlice( |
| 11874 | sema: *Sema, | 11928 | sema: *Sema, |
| 11875 | block: *Block, | 11929 | block: *Block, |
| 11876 | dest_type: Type, | 11930 | dest_ty: Type, |
| 11877 | inst: Air.Inst.Ref, | 11931 | inst: Air.Inst.Ref, |
| 11878 | inst_src: LazySrcLoc, | 11932 | inst_src: LazySrcLoc, |
| 11879 | ) CompileError!Air.Inst.Ref { | 11933 | ) CompileError!Air.Inst.Ref { |
| 11880 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { | 11934 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 11881 | // The comptime Value representation is compatible with both types. | 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 | try sema.requireRuntimeBlock(block, inst_src); | 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 | fn coerceArrayPtrToMany( | 11942 | fn coerceArrayPtrToMany( |
| 11889 | sema: *Sema, | 11943 | sema: *Sema, |
| 11890 | block: *Block, | 11944 | block: *Block, |
| 11891 | dest_type: Type, | 11945 | dest_ty: Type, |
| 11892 | inst: Air.Inst.Ref, | 11946 | inst: Air.Inst.Ref, |
| 11893 | inst_src: LazySrcLoc, | 11947 | inst_src: LazySrcLoc, |
| 11894 | ) !Air.Inst.Ref { | 11948 | ) !Air.Inst.Ref { |
| 11895 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { | 11949 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 11896 | // The comptime Value representation is compatible with both types. | 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 | try sema.requireRuntimeBlock(block, inst_src); | 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 | fn analyzeDeclVal( | 12048 | fn analyzeDeclVal( |
| ... | @@ -12223,7 +12368,7 @@ fn cmpNumeric( | ... | @@ -12223,7 +12368,7 @@ fn cmpNumeric( |
| 12223 | const target = sema.mod.getTarget(); | 12368 | const target = sema.mod.getTarget(); |
| 12224 | if (lhs_is_float and rhs_is_float) { | 12369 | if (lhs_is_float and rhs_is_float) { |
| 12225 | // Implicit cast the smaller one to the larger one. | 12370 | // Implicit cast the smaller one to the larger one. |
| 12226 | const dest_type = x: { | 12371 | const dest_ty = x: { |
| 12227 | if (lhs_ty_tag == .ComptimeFloat) { | 12372 | if (lhs_ty_tag == .ComptimeFloat) { |
| 12228 | break :x rhs_ty; | 12373 | break :x rhs_ty; |
| 12229 | } else if (rhs_ty_tag == .ComptimeFloat) { | 12374 | } else if (rhs_ty_tag == .ComptimeFloat) { |
| ... | @@ -12235,8 +12380,8 @@ fn cmpNumeric( | ... | @@ -12235,8 +12380,8 @@ fn cmpNumeric( |
| 12235 | break :x rhs_ty; | 12380 | break :x rhs_ty; |
| 12236 | } | 12381 | } |
| 12237 | }; | 12382 | }; |
| 12238 | const casted_lhs = try sema.coerce(block, dest_type, lhs, lhs_src); | 12383 | const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src); |
| 12239 | const casted_rhs = try sema.coerce(block, dest_type, rhs, rhs_src); | 12384 | const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src); |
| 12240 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs); | 12385 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs); |
| 12241 | } | 12386 | } |
| 12242 | // For mixed unsigned integer sizes, implicit cast both operands to the larger integer. | 12387 | // For mixed unsigned integer sizes, implicit cast both operands to the larger integer. |
| ... | @@ -12327,7 +12472,7 @@ fn cmpNumeric( | ... | @@ -12327,7 +12472,7 @@ fn cmpNumeric( |
| 12327 | rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed); | 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 | const max_bits = std.math.max(lhs_bits, rhs_bits); | 12476 | const max_bits = std.math.max(lhs_bits, rhs_bits); |
| 12332 | const casted_bits = std.math.cast(u16, max_bits) catch |err| switch (err) { | 12477 | const casted_bits = std.math.cast(u16, max_bits) catch |err| switch (err) { |
| 12333 | error.Overflow => return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits}), | 12478 | error.Overflow => return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits}), |
| ... | @@ -12335,8 +12480,8 @@ fn cmpNumeric( | ... | @@ -12335,8 +12480,8 @@ fn cmpNumeric( |
| 12335 | const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned; | 12480 | const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned; |
| 12336 | break :blk try Module.makeIntType(sema.arena, signedness, casted_bits); | 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); | 12483 | const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src); |
| 12339 | const casted_rhs = try sema.coerce(block, dest_type, rhs, rhs_src); | 12484 | const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src); |
| 12340 | | 12485 | |
| 12341 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs); | 12486 | return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs); |
| 12342 | } | 12487 | } |
| ... | @@ -12344,32 +12489,32 @@ fn cmpNumeric( | ... | @@ -12344,32 +12489,32 @@ fn cmpNumeric( |
| 12344 | fn wrapOptional( | 12489 | fn wrapOptional( |
| 12345 | sema: *Sema, | 12490 | sema: *Sema, |
| 12346 | block: *Block, | 12491 | block: *Block, |
| 12347 | dest_type: Type, | 12492 | dest_ty: Type, |
| 12348 | inst: Air.Inst.Ref, | 12493 | inst: Air.Inst.Ref, |
| 12349 | inst_src: LazySrcLoc, | 12494 | inst_src: LazySrcLoc, |
| 12350 | ) !Air.Inst.Ref { | 12495 | ) !Air.Inst.Ref { |
| 12351 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 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 | try sema.requireRuntimeBlock(block, inst_src); | 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 | fn wrapErrorUnion( | 12504 | fn wrapErrorUnion( |
| 12360 | sema: *Sema, | 12505 | sema: *Sema, |
| 12361 | block: *Block, | 12506 | block: *Block, |
| 12362 | dest_type: Type, | 12507 | dest_ty: Type, |
| 12363 | inst: Air.Inst.Ref, | 12508 | inst: Air.Inst.Ref, |
| 12364 | inst_src: LazySrcLoc, | 12509 | inst_src: LazySrcLoc, |
| 12365 | ) !Air.Inst.Ref { | 12510 | ) !Air.Inst.Ref { |
| 12366 | const inst_ty = sema.typeOf(inst); | 12511 | const inst_ty = sema.typeOf(inst); |
| 12367 | const dest_err_set_ty = dest_type.errorUnionSet(); | 12512 | const dest_err_set_ty = dest_ty.errorUnionSet(); |
| 12368 | const dest_payload_ty = dest_type.errorUnionPayload(); | 12513 | const dest_payload_ty = dest_ty.errorUnionPayload(); |
| 12369 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 12514 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 12370 | if (inst_ty.zigTypeTag() != .ErrorSet) { | 12515 | if (inst_ty.zigTypeTag() != .ErrorSet) { |
| 12371 | _ = try sema.coerce(block, dest_payload_ty, inst, inst_src); | 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 | switch (dest_err_set_ty.tag()) { | 12519 | switch (dest_err_set_ty.tag()) { |
| 12375 | .anyerror => {}, | 12520 | .anyerror => {}, |
| ... | @@ -12417,7 +12562,7 @@ fn wrapErrorUnion( | ... | @@ -12417,7 +12562,7 @@ fn wrapErrorUnion( |
| 12417 | }, | 12562 | }, |
| 12418 | else => unreachable, | 12563 | else => unreachable, |
| 12419 | } | 12564 | } |
| 12420 | return sema.addConstant(dest_type, val); | 12565 | return sema.addConstant(dest_ty, val); |
| 12421 | } | 12566 | } |
| 12422 | | 12567 | |
| 12423 | try sema.requireRuntimeBlock(block, inst_src); | 12568 | try sema.requireRuntimeBlock(block, inst_src); |
| ... | @@ -12425,25 +12570,25 @@ fn wrapErrorUnion( | ... | @@ -12425,25 +12570,25 @@ fn wrapErrorUnion( |
| 12425 | // we are coercing from E to E!T | 12570 | // we are coercing from E to E!T |
| 12426 | if (inst_ty.zigTypeTag() == .ErrorSet) { | 12571 | if (inst_ty.zigTypeTag() == .ErrorSet) { |
| 12427 | var coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src); | 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 | } else { | 12574 | } else { |
| 12430 | var coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src); | 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 | fn unionToTag( | 12580 | fn unionToTag( |
| 12436 | sema: *Sema, | 12581 | sema: *Sema, |
| 12437 | block: *Block, | 12582 | block: *Block, |
| 12438 | dest_type: Type, | 12583 | dest_ty: Type, |
| 12439 | un: Air.Inst.Ref, | 12584 | un: Air.Inst.Ref, |
| 12440 | un_src: LazySrcLoc, | 12585 | un_src: LazySrcLoc, |
| 12441 | ) !Air.Inst.Ref { | 12586 | ) !Air.Inst.Ref { |
| 12442 | if (try sema.resolveMaybeUndefVal(block, un_src, un)) |un_val| { | 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 | try sema.requireRuntimeBlock(block, un_src); | 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 | fn resolvePeerTypes( | 12594 | fn resolvePeerTypes( |