| ... | @@ -12358,31 +12358,6 @@ fn coerce( | ... | @@ -12358,31 +12358,6 @@ fn coerce( |
| 12358 | // T to E!T or E to E!T | 12358 | // T to E!T or E to E!T |
| 12359 | return sema.wrapErrorUnion(block, dest_ty, inst, inst_src); | 12359 | return sema.wrapErrorUnion(block, dest_ty, inst, inst_src); |
| 12360 | }, | 12360 | }, |
| 12361 | .ErrorSet => switch (inst_ty.zigTypeTag()) { | | |
| 12362 | .ErrorSet => { | | |
| 12363 | // Coercion to `anyerror`. Note that this check can return false positives | | |
| 12364 | // in case the error sets did not get resolved. | | |
| 12365 | if (dest_ty.isAnyError()) { | | |
| 12366 | return sema.coerceCompatibleErrorSets(block, inst, inst_src); | | |
| 12367 | } | | |
| 12368 | // If both are inferred error sets of functions, and | | |
| 12369 | // the dest includes the source function, the coercion is OK. | | |
| 12370 | // This check is important because it works without forcing a full resolution | | |
| 12371 | // of inferred error sets. | | |
| 12372 | if (inst_ty.castTag(.error_set_inferred)) |src_payload| { | | |
| 12373 | if (dest_ty.castTag(.error_set_inferred)) |dst_payload| { | | |
| 12374 | const src_func = src_payload.data.func; | | |
| 12375 | const dst_func = dst_payload.data.func; | | |
| 12376 | | | |
| 12377 | if (src_func == dst_func or dst_payload.data.functions.contains(src_func)) { | | |
| 12378 | return sema.coerceCompatibleErrorSets(block, inst, inst_src); | | |
| 12379 | } | | |
| 12380 | } | | |
| 12381 | } | | |
| 12382 | // TODO full error set resolution and compare sets by names. | | |
| 12383 | }, | | |
| 12384 | else => {}, | | |
| 12385 | }, | | |
| 12386 | .Union => switch (inst_ty.zigTypeTag()) { | 12361 | .Union => switch (inst_ty.zigTypeTag()) { |
| 12387 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), | 12362 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), |
| 12388 | else => {}, | 12363 | else => {}, |
| ... | @@ -12440,15 +12415,47 @@ fn coerceInMemoryAllowed(dest_ty: Type, src_ty: Type, dest_is_mut: bool, target: | ... | @@ -12440,15 +12415,47 @@ fn coerceInMemoryAllowed(dest_ty: Type, src_ty: Type, dest_is_mut: bool, target: |
| 12440 | return coerceInMemoryAllowedFns(dest_ty, src_ty, target); | 12415 | return coerceInMemoryAllowedFns(dest_ty, src_ty, target); |
| 12441 | } | 12416 | } |
| 12442 | | 12417 | |
| | 12418 | // Error Sets |
| | 12419 | if (dest_ty.zigTypeTag() == .ErrorSet and src_ty.zigTypeTag() == .ErrorSet) { |
| | 12420 | return coerceInMemoryAllowedErrorSets(dest_ty, src_ty); |
| | 12421 | } |
| | 12422 | |
| 12443 | // TODO: arrays | 12423 | // TODO: arrays |
| 12444 | // TODO: non-pointer-like optionals | 12424 | // TODO: non-pointer-like optionals |
| 12445 | // TODO: error unions | 12425 | // TODO: error unions |
| 12446 | // TODO: error sets | | |
| 12447 | // TODO: vectors | 12426 | // TODO: vectors |
| 12448 | | 12427 | |
| 12449 | return .no_match; | 12428 | return .no_match; |
| 12450 | } | 12429 | } |
| 12451 | | 12430 | |
| | 12431 | fn coerceInMemoryAllowedErrorSets( |
| | 12432 | dest_ty: Type, |
| | 12433 | src_ty: Type, |
| | 12434 | ) InMemoryCoercionResult { |
| | 12435 | // Coercion to `anyerror`. Note that this check can return false positives |
| | 12436 | // in case the error sets did not get resolved. |
| | 12437 | if (dest_ty.isAnyError()) { |
| | 12438 | return .ok; |
| | 12439 | } |
| | 12440 | // If both are inferred error sets of functions, and |
| | 12441 | // the dest includes the source function, the coercion is OK. |
| | 12442 | // This check is important because it works without forcing a full resolution |
| | 12443 | // of inferred error sets. |
| | 12444 | if (src_ty.castTag(.error_set_inferred)) |src_payload| { |
| | 12445 | if (dest_ty.castTag(.error_set_inferred)) |dst_payload| { |
| | 12446 | const src_func = src_payload.data.func; |
| | 12447 | const dst_func = dst_payload.data.func; |
| | 12448 | |
| | 12449 | if (src_func == dst_func or dst_payload.data.functions.contains(src_func)) { |
| | 12450 | return .ok; |
| | 12451 | } |
| | 12452 | } |
| | 12453 | } |
| | 12454 | |
| | 12455 | // TODO full error set resolution and compare sets by names. |
| | 12456 | return .no_match; |
| | 12457 | } |
| | 12458 | |
| 12452 | fn coerceInMemoryAllowedFns( | 12459 | fn coerceInMemoryAllowedFns( |
| 12453 | dest_ty: Type, | 12460 | dest_ty: Type, |
| 12454 | src_ty: Type, | 12461 | src_ty: Type, |
| ... | @@ -13224,26 +13231,6 @@ fn coerceVectorInMemory( | ... | @@ -13224,26 +13231,6 @@ fn coerceVectorInMemory( |
| 13224 | return block.addBitCast(dest_ty, inst); | 13231 | return block.addBitCast(dest_ty, inst); |
| 13225 | } | 13232 | } |
| 13226 | | 13233 | |
| 13227 | fn coerceCompatibleErrorSets( | | |
| 13228 | sema: *Sema, | | |
| 13229 | block: *Block, | | |
| 13230 | err_set: Air.Inst.Ref, | | |
| 13231 | err_set_src: LazySrcLoc, | | |
| 13232 | ) !Air.Inst.Ref { | | |
| 13233 | if (try sema.resolveDefinedValue(block, err_set_src, err_set)) |err_set_val| { | | |
| 13234 | // Same representation works. | | |
| 13235 | return sema.addConstant(Type.anyerror, err_set_val); | | |
| 13236 | } | | |
| 13237 | try sema.requireRuntimeBlock(block, err_set_src); | | |
| 13238 | return block.addInst(.{ | | |
| 13239 | .tag = .bitcast, | | |
| 13240 | .data = .{ .ty_op = .{ | | |
| 13241 | .ty = Air.Inst.Ref.anyerror_type, | | |
| 13242 | .operand = err_set, | | |
| 13243 | } }, | | |
| 13244 | }); | | |
| 13245 | } | | |
| 13246 | | | |
| 13247 | fn analyzeDeclVal( | 13234 | fn analyzeDeclVal( |
| 13248 | sema: *Sema, | 13235 | sema: *Sema, |
| 13249 | block: *Block, | 13236 | block: *Block, |