| ... | @@ -6945,6 +6945,12 @@ fn zirSwitchCapture( | ... | @@ -6945,6 +6945,12 @@ fn zirSwitchCapture( |
| 6945 | const operand_ptr = sema.resolveInst(cond_info.operand); | 6945 | const operand_ptr = sema.resolveInst(cond_info.operand); |
| 6946 | const operand_ptr_ty = sema.typeOf(operand_ptr); | 6946 | const operand_ptr_ty = sema.typeOf(operand_ptr); |
| 6947 | const operand_ty = if (operand_is_ref) operand_ptr_ty.childType() else operand_ptr_ty; | 6947 | const operand_ty = if (operand_is_ref) operand_ptr_ty.childType() else operand_ptr_ty; |
| | 6948 | const target = sema.mod.getTarget(); |
| | 6949 | |
| | 6950 | const operand = if (operand_is_ref) |
| | 6951 | try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src) |
| | 6952 | else |
| | 6953 | operand_ptr; |
| 6948 | | 6954 | |
| 6949 | if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) { | 6955 | if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) { |
| 6950 | // It is the else/`_` prong. | 6956 | // It is the else/`_` prong. |
| ... | @@ -6953,42 +6959,57 @@ fn zirSwitchCapture( | ... | @@ -6953,42 +6959,57 @@ fn zirSwitchCapture( |
| 6953 | return operand_ptr; | 6959 | return operand_ptr; |
| 6954 | } | 6960 | } |
| 6955 | | 6961 | |
| 6956 | const operand = if (operand_is_ref) | | |
| 6957 | try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src) | | |
| 6958 | else | | |
| 6959 | operand_ptr; | | |
| 6960 | | | |
| 6961 | switch (operand_ty.zigTypeTag()) { | 6962 | switch (operand_ty.zigTypeTag()) { |
| 6962 | .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src), | 6963 | .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src), |
| 6963 | else => return operand, | 6964 | else => return operand, |
| 6964 | } | 6965 | } |
| 6965 | } | 6966 | } |
| 6966 | | 6967 | |
| 6967 | if (is_multi) { | 6968 | const items = if (is_multi) |
| 6968 | return sema.fail(block, switch_src, "TODO implement Sema for switch capture multi", .{}); | 6969 | switch_extra.data.getMultiProng(sema.code, switch_extra.end, capture_info.prong_index).items |
| 6969 | } | 6970 | else |
| 6970 | const scalar_prong = switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index); | 6971 | &[_]Zir.Inst.Ref{ |
| 6971 | const item = sema.resolveInst(scalar_prong.item); | 6972 | switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index).item, |
| 6972 | // Previous switch validation ensured this will succeed | 6973 | }; |
| 6973 | const item_val = sema.resolveConstValue(block, .unneeded, item) catch unreachable; | | |
| 6974 | const target = sema.mod.getTarget(); | | |
| 6975 | | 6974 | |
| 6976 | switch (operand_ty.zigTypeTag()) { | 6975 | switch (operand_ty.zigTypeTag()) { |
| 6977 | .Union => { | 6976 | .Union => { |
| 6978 | const union_obj = operand_ty.cast(Type.Payload.Union).?.data; | 6977 | const union_obj = operand_ty.cast(Type.Payload.Union).?.data; |
| 6979 | const enum_ty = union_obj.tag_ty; | 6978 | const enum_ty = union_obj.tag_ty; |
| 6980 | | 6979 | |
| 6981 | const field_index_usize = enum_ty.enumTagFieldIndex(item_val, target).?; | 6980 | const first_item = sema.resolveInst(items[0]); |
| 6982 | const field_index = @intCast(u32, field_index_usize); | 6981 | // Previous switch validation ensured this will succeed |
| 6983 | const field = union_obj.fields.values()[field_index]; | 6982 | const first_item_val = sema.resolveConstValue(block, .unneeded, first_item) catch unreachable; |
| | 6983 | |
| | 6984 | const first_field_index = @intCast(u32, enum_ty.enumTagFieldIndex(first_item_val, target).?); |
| | 6985 | const first_field = union_obj.fields.values()[first_field_index]; |
| 6984 | | 6986 | |
| 6985 | // TODO handle multiple union tags which have compatible types | 6987 | for (items[1..]) |item| { |
| | 6988 | const item_ref = sema.resolveInst(item); |
| | 6989 | // Previous switch validation ensured this will succeed |
| | 6990 | const item_val = sema.resolveConstValue(block, .unneeded, item_ref) catch unreachable; |
| | 6991 | |
| | 6992 | const field_index = enum_ty.enumTagFieldIndex(item_val, target).?; |
| | 6993 | const field = union_obj.fields.values()[field_index]; |
| | 6994 | if (!field.ty.eql(first_field.ty, target)) { |
| | 6995 | const first_item_src = switch_src; // TODO better source location |
| | 6996 | const item_src = switch_src; |
| | 6997 | const msg = msg: { |
| | 6998 | const msg = try sema.errMsg(block, switch_src, "capture group with incompatible types", .{}); |
| | 6999 | errdefer msg.destroy(sema.gpa); |
| | 7000 | try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(target)}); |
| | 7001 | try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(target)}); |
| | 7002 | break :msg msg; |
| | 7003 | }; |
| | 7004 | return sema.failWithOwnedErrorMsg(block, msg); |
| | 7005 | } |
| | 7006 | } |
| 6986 | | 7007 | |
| 6987 | if (is_ref) { | 7008 | if (is_ref) { |
| 6988 | assert(operand_is_ref); | 7009 | assert(operand_is_ref); |
| 6989 | | 7010 | |
| 6990 | const field_ty_ptr = try Type.ptr(sema.arena, target, .{ | 7011 | const field_ty_ptr = try Type.ptr(sema.arena, target, .{ |
| 6991 | .pointee_type = field.ty, | 7012 | .pointee_type = first_field.ty, |
| 6992 | .@"addrspace" = .generic, | 7013 | .@"addrspace" = .generic, |
| 6993 | .mutable = operand_ptr_ty.ptrIsMutable(), | 7014 | .mutable = operand_ptr_ty.ptrIsMutable(), |
| 6994 | }); | 7015 | }); |
| ... | @@ -6999,30 +7020,48 @@ fn zirSwitchCapture( | ... | @@ -6999,30 +7020,48 @@ fn zirSwitchCapture( |
| 6999 | try Value.Tag.field_ptr.create(sema.arena, .{ | 7020 | try Value.Tag.field_ptr.create(sema.arena, .{ |
| 7000 | .container_ptr = op_ptr_val, | 7021 | .container_ptr = op_ptr_val, |
| 7001 | .container_ty = operand_ty, | 7022 | .container_ty = operand_ty, |
| 7002 | .field_index = field_index, | 7023 | .field_index = first_field_index, |
| 7003 | }), | 7024 | }), |
| 7004 | ); | 7025 | ); |
| 7005 | } | 7026 | } |
| 7006 | try sema.requireRuntimeBlock(block, operand_src); | 7027 | try sema.requireRuntimeBlock(block, operand_src); |
| 7007 | return block.addStructFieldPtr(operand_ptr, field_index, field_ty_ptr); | 7028 | return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr); |
| 7008 | } | 7029 | } |
| 7009 | | 7030 | |
| 7010 | const operand = if (operand_is_ref) | | |
| 7011 | try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src) | | |
| 7012 | else | | |
| 7013 | operand_ptr; | | |
| 7014 | | | |
| 7015 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| { | 7031 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| { |
| 7016 | return sema.addConstant( | 7032 | return sema.addConstant( |
| 7017 | field.ty, | 7033 | first_field.ty, |
| 7018 | operand_val.castTag(.@"union").?.data.val, | 7034 | operand_val.castTag(.@"union").?.data.val, |
| 7019 | ); | 7035 | ); |
| 7020 | } | 7036 | } |
| 7021 | try sema.requireRuntimeBlock(block, operand_src); | 7037 | try sema.requireRuntimeBlock(block, operand_src); |
| 7022 | return block.addStructFieldVal(operand, field_index, field.ty); | 7038 | return block.addStructFieldVal(operand, first_field_index, first_field.ty); |
| 7023 | }, | 7039 | }, |
| 7024 | .ErrorSet => { | 7040 | .ErrorSet => { |
| 7025 | return sema.fail(block, operand_src, "TODO implement Sema for zirSwitchCapture for error sets", .{}); | 7041 | if (is_multi) { |
| | 7042 | var names: Module.ErrorSet.NameMap = .{}; |
| | 7043 | try names.ensureUnusedCapacity(sema.arena, items.len); |
| | 7044 | for (items) |item| { |
| | 7045 | const item_ref = sema.resolveInst(item); |
| | 7046 | // Previous switch validation ensured this will succeed |
| | 7047 | const item_val = sema.resolveConstValue(block, .unneeded, item_ref) catch unreachable; |
| | 7048 | names.putAssumeCapacityNoClobber( |
| | 7049 | item_val.getError().?, |
| | 7050 | {}, |
| | 7051 | ); |
| | 7052 | } |
| | 7053 | // names must be sorted |
| | 7054 | Module.ErrorSet.sortNames(&names); |
| | 7055 | const else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names); |
| | 7056 | |
| | 7057 | return sema.bitCast(block, else_error_ty, operand, operand_src); |
| | 7058 | } else { |
| | 7059 | // Previous switch validation ensured this will succeed |
| | 7060 | const item_val = sema.resolveConstValue(block, .unneeded, items[0]) catch unreachable; |
| | 7061 | |
| | 7062 | const item_ty = try Type.Tag.error_set_single.create(sema.arena, item_val.getError().?); |
| | 7063 | return sema.bitCast(block, item_ty, operand, operand_src); |
| | 7064 | } |
| 7026 | }, | 7065 | }, |
| 7027 | else => { | 7066 | else => { |
| 7028 | return sema.fail(block, operand_src, "switch on type '{}' provides no capture value", .{ | 7067 | return sema.fail(block, operand_src, "switch on type '{}' provides no capture value", .{ |
| ... | @@ -7390,6 +7429,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -7390,6 +7429,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7390 | names.putAssumeCapacityNoClobber(error_name, {}); | 7429 | names.putAssumeCapacityNoClobber(error_name, {}); |
| 7391 | } | 7430 | } |
| 7392 | | 7431 | |
| | 7432 | // names must be sorted |
| | 7433 | Module.ErrorSet.sortNames(&names); |
| 7393 | else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names); | 7434 | else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names); |
| 7394 | } | 7435 | } |
| 7395 | }, | 7436 | }, |
| ... | @@ -7743,6 +7784,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -7743,6 +7784,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7743 | } | 7784 | } |
| 7744 | | 7785 | |
| 7745 | if (scalar_cases_len + multi_cases_len == 0) { | 7786 | if (scalar_cases_len + multi_cases_len == 0) { |
| | 7787 | if (special_prong == .none) { |
| | 7788 | return sema.fail(block, src, "switch must handle all possibilities", .{}); |
| | 7789 | } |
| 7746 | return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges); | 7790 | return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges); |
| 7747 | } | 7791 | } |
| 7748 | | 7792 | |
| ... | @@ -12233,7 +12277,9 @@ fn zirStructInit( | ... | @@ -12233,7 +12277,9 @@ fn zirStructInit( |
| 12233 | return alloc; | 12277 | return alloc; |
| 12234 | } | 12278 | } |
| 12235 | | 12279 | |
| 12236 | return sema.fail(block, src, "TODO: Sema.zirStructInit for runtime-known union values", .{}); | 12280 | try sema.requireRuntimeBlock(block, src); |
| | 12281 | try sema.queueFullTypeResolution(resolved_ty); |
| | 12282 | return block.addUnionInit(resolved_ty, field_index, init_inst); |
| 12237 | } | 12283 | } |
| 12238 | unreachable; | 12284 | unreachable; |
| 12239 | } | 12285 | } |
| ... | @@ -12976,6 +13022,8 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12976,6 +13022,8 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12976 | ); | 13022 | ); |
| 12977 | } | 13023 | } |
| 12978 | | 13024 | |
| | 13025 | // names must be sorted |
| | 13026 | Module.ErrorSet.sortNames(&names); |
| 12979 | const ty = try Type.Tag.error_set_merged.create(sema.arena, names); | 13027 | const ty = try Type.Tag.error_set_merged.create(sema.arena, names); |
| 12980 | return sema.addType(ty); | 13028 | return sema.addType(ty); |
| 12981 | }, | 13029 | }, |