diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index d8fb92092..97354e0f6 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -239,8 +239,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^runtime.Type_Info) { case runtime.Type_Info_Named: write_string(buf, info.name); case runtime.Type_Info_Integer: - a := any{id = ti.id}; - switch in a { + switch ti.id { case int: write_string(buf, "int"); case uint: write_string(buf, "uint"); case uintptr: write_string(buf, "uintptr"); @@ -263,8 +262,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^runtime.Type_Info) { write_string(buf, "string"); } case runtime.Type_Info_Boolean: - a := any{id = ti.id}; - switch in a { + switch ti.id { case bool: write_string(buf, "bool"); case: write_byte(buf, 'b'); diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 80ade1272..3380412d7 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -63,8 +63,7 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) { case Type_Info_Named: os.write_string(fd, info.name); case Type_Info_Integer: - a := any{id = ti.id}; - switch _ in a { + switch ti.id { case int: os.write_string(fd, "int"); case uint: os.write_string(fd, "uint"); case uintptr: os.write_string(fd, "uintptr"); @@ -83,8 +82,7 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) { case Type_Info_String: os.write_string(fd, "string"); case Type_Info_Boolean: - a := any{id = ti.id}; - switch _ in a { + switch ti.id { case bool: os.write_string(fd, "bool"); case: os.write_byte(fd, 'b'); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 94de84f86..0ae83f1ed 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -729,32 +729,46 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { add_constant_switch_case(ctx, &seen, rhs); } else { Operand y = {}; - check_expr(ctx, &y, expr); + if (is_type_typeid(x.type)) { + check_expr_or_type(ctx, &y, expr, x.type); + } else { + check_expr(ctx, &y, expr); + } if (x.mode == Addressing_Invalid || y.mode == Addressing_Invalid) { continue; } - convert_to_typed(ctx, &y, x.type); - if (y.mode == Addressing_Invalid) { - continue; - } - - // NOTE(bill): the ordering here matters - Operand z = y; - check_comparison(ctx, &z, &x, Token_CmpEq); - if (z.mode == Addressing_Invalid) { - continue; - } - if (y.mode != Addressing_Constant) { - if (complete) { - error(y.expr, "#complete switch statement only allows constant case clauses"); + if (y.mode == Addressing_Type) { + Type *t = y.type; + if (t == nullptr || t == t_invalid || is_type_polymorphic(t)) { + error(y.expr, "Invalid type for case clause"); + continue; + } + t = default_type(t); + add_type_info_type(ctx, t); + } else { + convert_to_typed(ctx, &y, x.type); + if (y.mode == Addressing_Invalid) { + continue; } - continue; - } - add_constant_switch_case(ctx, &seen, y); + // NOTE(bill): the ordering here matters + Operand z = y; + check_comparison(ctx, &z, &x, Token_CmpEq); + if (z.mode == Addressing_Invalid) { + continue; + } + if (y.mode != Addressing_Constant) { + if (complete) { + error(y.expr, "#complete switch statement only allows constant case clauses"); + } + continue; + } + + add_constant_switch_case(ctx, &seen, y); + } } } diff --git a/src/ir.cpp b/src/ir.cpp index ffd9f4f67..b51b9c184 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7145,7 +7145,14 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { irValue *cond_rhs = ir_emit_comp(proc, op, tag, rhs); cond = ir_emit_arith(proc, Token_And, cond_lhs, cond_rhs, t_bool); } else { - cond = ir_emit_comp(proc, Token_CmpEq, tag, ir_build_expr(proc, expr)); + if (expr->tav.mode == Addressing_Type) { + GB_ASSERT(is_type_typeid(ir_type(tag))); + irValue *e = ir_typeid(proc->module, expr->tav.type); + e = ir_emit_conv(proc, e, ir_type(tag)); + cond = ir_emit_comp(proc, Token_CmpEq, tag, e); + } else { + cond = ir_emit_comp(proc, Token_CmpEq, tag, ir_build_expr(proc, expr)); + } } ir_emit_if(proc, cond, body, next_cond); ir_start_block(proc, next_cond);