mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
avoid codegening functions never called from conditional compilation
This commit is contained in:
parent
9bf9be9937
commit
b8a1cb299e
@ -1207,6 +1207,9 @@ struct BlockContext {
|
|||||||
|
|
||||||
LLVMZigDIScope *di_scope;
|
LLVMZigDIScope *di_scope;
|
||||||
Buf *c_import_buf;
|
Buf *c_import_buf;
|
||||||
|
|
||||||
|
// if this is true, then this code will not be generated
|
||||||
|
bool codegen_excluded;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
271
src/analyze.cpp
271
src/analyze.cpp
@ -27,7 +27,8 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
|
|||||||
static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
TypeTableEntry *expected_type, AstNode *node);
|
TypeTableEntry *expected_type, AstNode *node);
|
||||||
static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
|
static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
|
||||||
static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);
|
static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context,
|
||||||
|
FnTableEntry *fn);
|
||||||
static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type);
|
static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type);
|
||||||
static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
|
static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
|
||||||
TypeTableEntry *expected_type, uint64_t x);
|
TypeTableEntry *expected_type, uint64_t x);
|
||||||
@ -1990,6 +1991,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
|
|||||||
if (parent) {
|
if (parent) {
|
||||||
context->parent_loop_node = parent->parent_loop_node;
|
context->parent_loop_node = parent->parent_loop_node;
|
||||||
context->c_import_buf = parent->c_import_buf;
|
context->c_import_buf = parent->c_import_buf;
|
||||||
|
context->codegen_excluded = parent->codegen_excluded;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node && node->type == NodeTypeFnDef) {
|
if (node && node->type == NodeTypeFnDef) {
|
||||||
@ -2271,7 +2273,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
|
|||||||
auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(field_name);
|
auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(field_name);
|
||||||
if (table_entry) {
|
if (table_entry) {
|
||||||
node->data.field_access_expr.is_member_fn = true;
|
node->data.field_access_expr.is_member_fn = true;
|
||||||
return resolve_expr_const_val_as_fn(g, node, table_entry->value);
|
return resolve_expr_const_val_as_fn(g, node, context, table_entry->value);
|
||||||
} else {
|
} else {
|
||||||
add_node_error(g, node, buf_sprintf("no member named '%s' in '%s'",
|
add_node_error(g, node, buf_sprintf("no member named '%s' in '%s'",
|
||||||
buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
|
buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
|
||||||
@ -2304,7 +2306,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
|
|||||||
} else if (child_type->id == TypeTableEntryIdStruct) {
|
} else if (child_type->id == TypeTableEntryIdStruct) {
|
||||||
auto entry = child_type->data.structure.fn_table.maybe_get(field_name);
|
auto entry = child_type->data.structure.fn_table.maybe_get(field_name);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
return resolve_expr_const_val_as_fn(g, node, entry->value);
|
return resolve_expr_const_val_as_fn(g, node, context, entry->value);
|
||||||
} else {
|
} else {
|
||||||
add_node_error(g, node,
|
add_node_error(g, node,
|
||||||
buf_sprintf("struct '%s' has no function called '%s'",
|
buf_sprintf("struct '%s' has no function called '%s'",
|
||||||
@ -2421,8 +2423,12 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode
|
|||||||
return other_expr->type_entry;
|
return other_expr->type_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {
|
static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context,
|
||||||
fn->ref_count += 1;
|
FnTableEntry *fn)
|
||||||
|
{
|
||||||
|
if (!context->codegen_excluded) {
|
||||||
|
fn->ref_count += 1;
|
||||||
|
}
|
||||||
Expr *expr = get_resolved_expr(node);
|
Expr *expr = get_resolved_expr(node);
|
||||||
expr->const_val.ok = true;
|
expr->const_val.ok = true;
|
||||||
expr->const_val.data.x_fn = fn;
|
expr->const_val.data.x_fn = fn;
|
||||||
@ -2604,7 +2610,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
|
|||||||
if (fn_table_entry) {
|
if (fn_table_entry) {
|
||||||
assert(fn_table_entry->value->type_entry);
|
assert(fn_table_entry->value->type_entry);
|
||||||
node->data.symbol_expr.fn_entry = fn_table_entry->value;
|
node->data.symbol_expr.fn_entry = fn_table_entry->value;
|
||||||
return resolve_expr_const_val_as_fn(g, node, fn_table_entry->value);
|
return resolve_expr_const_val_as_fn(g, node, context, fn_table_entry->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
|
add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
|
||||||
@ -4344,7 +4350,9 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
|
|||||||
|
|
||||||
node->data.fn_call_expr.fn_entry = fn_table_entry;
|
node->data.fn_call_expr.fn_entry = fn_table_entry;
|
||||||
|
|
||||||
fn_table_entry->ref_count += 1;
|
if (!context->codegen_excluded) {
|
||||||
|
fn_table_entry->ref_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
|
return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
|
||||||
|
|
||||||
@ -4650,6 +4658,13 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
|
|||||||
{
|
{
|
||||||
AstNode **expr_node = &node->data.switch_expr.expr;
|
AstNode **expr_node = &node->data.switch_expr.expr;
|
||||||
TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
|
TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
|
||||||
|
ConstExprValue *expr_val = &get_resolved_expr(*expr_node)->const_val;
|
||||||
|
if (expr_val->ok && !expr_val->depends_on_compile_var) {
|
||||||
|
add_node_error(g, first_executing_node(*expr_node),
|
||||||
|
buf_sprintf("value is constant; unnecessary switch statement"));
|
||||||
|
}
|
||||||
|
ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
|
||||||
|
|
||||||
|
|
||||||
int prong_count = node->data.switch_expr.prongs.length;
|
int prong_count = node->data.switch_expr.prongs.length;
|
||||||
AstNode **peer_nodes = allocate<AstNode*>(prong_count);
|
AstNode **peer_nodes = allocate<AstNode*>(prong_count);
|
||||||
@ -4662,113 +4677,132 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
|
|||||||
add_node_error(g, first_executing_node(*expr_node),
|
add_node_error(g, first_executing_node(*expr_node),
|
||||||
buf_sprintf("switch on unreachable expression not allowed"));
|
buf_sprintf("switch on unreachable expression not allowed"));
|
||||||
return g->builtin_types.entry_invalid;
|
return g->builtin_types.entry_invalid;
|
||||||
} else {
|
}
|
||||||
int *field_use_counts = nullptr;
|
|
||||||
if (expr_type->id == TypeTableEntryIdEnum) {
|
|
||||||
field_use_counts = allocate<int>(expr_type->data.enumeration.field_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *else_prong = nullptr;
|
|
||||||
for (int prong_i = 0; prong_i < prong_count; prong_i += 1) {
|
|
||||||
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
|
|
||||||
|
|
||||||
TypeTableEntry *var_type;
|
int *field_use_counts = nullptr;
|
||||||
bool var_is_target_expr;
|
if (expr_type->id == TypeTableEntryIdEnum) {
|
||||||
if (prong_node->data.switch_prong.items.length == 0) {
|
field_use_counts = allocate<int>(expr_type->data.enumeration.field_count);
|
||||||
if (else_prong) {
|
}
|
||||||
add_node_error(g, prong_node, buf_sprintf("multiple else prongs in switch expression"));
|
|
||||||
any_errors = true;
|
int const_chosen_prong_index = -1;
|
||||||
} else {
|
AstNode *else_prong = nullptr;
|
||||||
else_prong = prong_node;
|
for (int prong_i = 0; prong_i < prong_count; prong_i += 1) {
|
||||||
}
|
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
|
||||||
var_type = expr_type;
|
|
||||||
var_is_target_expr = true;
|
TypeTableEntry *var_type;
|
||||||
|
bool var_is_target_expr;
|
||||||
|
if (prong_node->data.switch_prong.items.length == 0) {
|
||||||
|
if (else_prong) {
|
||||||
|
add_node_error(g, prong_node, buf_sprintf("multiple else prongs in switch expression"));
|
||||||
|
any_errors = true;
|
||||||
} else {
|
} else {
|
||||||
bool all_agree_on_var_type = true;
|
else_prong = prong_node;
|
||||||
var_type = nullptr;
|
}
|
||||||
|
var_type = expr_type;
|
||||||
|
var_is_target_expr = true;
|
||||||
|
if (const_chosen_prong_index == -1) {
|
||||||
|
const_chosen_prong_index = prong_i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bool all_agree_on_var_type = true;
|
||||||
|
var_type = nullptr;
|
||||||
|
|
||||||
for (int item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) {
|
for (int item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) {
|
||||||
AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
|
AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
|
||||||
if (item_node->type == NodeTypeSwitchRange) {
|
if (item_node->type == NodeTypeSwitchRange) {
|
||||||
zig_panic("TODO range in switch statement");
|
zig_panic("TODO range in switch statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr_type->id == TypeTableEntryIdEnum) {
|
if (expr_type->id == TypeTableEntryIdEnum) {
|
||||||
if (item_node->type == NodeTypeSymbol) {
|
if (item_node->type == NodeTypeSymbol) {
|
||||||
Buf *field_name = &item_node->data.symbol_expr.symbol;
|
Buf *field_name = &item_node->data.symbol_expr.symbol;
|
||||||
TypeEnumField *type_enum_field = get_enum_field(expr_type, field_name);
|
TypeEnumField *type_enum_field = get_enum_field(expr_type, field_name);
|
||||||
if (type_enum_field) {
|
if (type_enum_field) {
|
||||||
item_node->data.symbol_expr.enum_field = type_enum_field;
|
item_node->data.symbol_expr.enum_field = type_enum_field;
|
||||||
if (!var_type) {
|
if (!var_type) {
|
||||||
var_type = type_enum_field->type_entry;
|
var_type = type_enum_field->type_entry;
|
||||||
}
|
}
|
||||||
if (type_enum_field->type_entry != var_type) {
|
if (type_enum_field->type_entry != var_type) {
|
||||||
all_agree_on_var_type = false;
|
all_agree_on_var_type = false;
|
||||||
}
|
}
|
||||||
uint32_t field_index = type_enum_field->value;
|
uint32_t field_index = type_enum_field->value;
|
||||||
assert(field_use_counts);
|
assert(field_use_counts);
|
||||||
field_use_counts[field_index] += 1;
|
field_use_counts[field_index] += 1;
|
||||||
if (field_use_counts[field_index] > 1) {
|
if (field_use_counts[field_index] > 1) {
|
||||||
add_node_error(g, item_node,
|
|
||||||
buf_sprintf("duplicate switch value: '%s'",
|
|
||||||
buf_ptr(type_enum_field->name)));
|
|
||||||
any_errors = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
add_node_error(g, item_node,
|
add_node_error(g, item_node,
|
||||||
buf_sprintf("enum '%s' has no field '%s'",
|
buf_sprintf("duplicate switch value: '%s'",
|
||||||
buf_ptr(&expr_type->name), buf_ptr(field_name)));
|
buf_ptr(type_enum_field->name)));
|
||||||
any_errors = true;
|
any_errors = true;
|
||||||
}
|
}
|
||||||
|
if (!any_errors && expr_val->ok) {
|
||||||
|
if (expr_val->data.x_enum.tag == type_enum_field->value) {
|
||||||
|
const_chosen_prong_index = prong_i;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
add_node_error(g, item_node, buf_sprintf("expected enum tag name"));
|
add_node_error(g, item_node,
|
||||||
|
buf_sprintf("enum '%s' has no field '%s'",
|
||||||
|
buf_ptr(&expr_type->name), buf_ptr(field_name)));
|
||||||
any_errors = true;
|
any_errors = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TypeTableEntry *item_type = analyze_expression(g, import, context, expr_type, item_node);
|
add_node_error(g, item_node, buf_sprintf("expected enum tag name"));
|
||||||
if (item_type->id != TypeTableEntryIdInvalid) {
|
any_errors = true;
|
||||||
ConstExprValue *const_val = &get_resolved_expr(item_node)->const_val;
|
}
|
||||||
if (!const_val->ok) {
|
} else {
|
||||||
add_node_error(g, item_node,
|
if (!any_errors && expr_val->ok) {
|
||||||
buf_sprintf("unable to resolve constant expression"));
|
zig_panic("TODO determine if const exprs are equal");
|
||||||
any_errors = true;
|
}
|
||||||
}
|
TypeTableEntry *item_type = analyze_expression(g, import, context, expr_type, item_node);
|
||||||
|
if (item_type->id != TypeTableEntryIdInvalid) {
|
||||||
|
ConstExprValue *const_val = &get_resolved_expr(item_node)->const_val;
|
||||||
|
if (!const_val->ok) {
|
||||||
|
add_node_error(g, item_node,
|
||||||
|
buf_sprintf("unable to resolve constant expression"));
|
||||||
|
any_errors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!var_type || !all_agree_on_var_type) {
|
|
||||||
var_type = expr_type;
|
|
||||||
var_is_target_expr = true;
|
|
||||||
} else {
|
|
||||||
var_is_target_expr = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!var_type || !all_agree_on_var_type) {
|
||||||
BlockContext *child_context = new_block_context(node, context);
|
var_type = expr_type;
|
||||||
prong_node->data.switch_prong.block_context = child_context;
|
var_is_target_expr = true;
|
||||||
AstNode *var_node = prong_node->data.switch_prong.var_symbol;
|
} else {
|
||||||
if (var_node) {
|
var_is_target_expr = false;
|
||||||
assert(var_node->type == NodeTypeSymbol);
|
|
||||||
Buf *var_name = &var_node->data.symbol_expr.symbol;
|
|
||||||
var_node->block_context = child_context;
|
|
||||||
prong_node->data.switch_prong.var = add_local_var(g, var_node, import,
|
|
||||||
child_context, var_name, var_type, true);
|
|
||||||
prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type,
|
|
||||||
prong_node->data.switch_prong.expr);
|
|
||||||
peer_nodes[prong_i] = prong_node->data.switch_prong.expr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr_type->id == TypeTableEntryIdEnum && !else_prong) {
|
BlockContext *child_context = new_block_context(node, context);
|
||||||
for (uint32_t i = 0; i < expr_type->data.enumeration.field_count; i += 1) {
|
prong_node->data.switch_prong.block_context = child_context;
|
||||||
if (field_use_counts[i] == 0) {
|
AstNode *var_node = prong_node->data.switch_prong.var_symbol;
|
||||||
add_node_error(g, node,
|
if (var_node) {
|
||||||
buf_sprintf("enumeration value '%s' not handled in switch",
|
assert(var_node->type == NodeTypeSymbol);
|
||||||
buf_ptr(expr_type->data.enumeration.fields[i].name)));
|
Buf *var_name = &var_node->data.symbol_expr.symbol;
|
||||||
any_errors = true;
|
var_node->block_context = child_context;
|
||||||
}
|
prong_node->data.switch_prong.var = add_local_var(g, var_node, import,
|
||||||
|
child_context, var_name, var_type, true);
|
||||||
|
prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int prong_i = 0; prong_i < prong_count; prong_i += 1) {
|
||||||
|
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
|
||||||
|
BlockContext *child_context = prong_node->data.switch_prong.block_context;
|
||||||
|
child_context->codegen_excluded = expr_val->ok && (const_chosen_prong_index != prong_i);
|
||||||
|
|
||||||
|
peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type,
|
||||||
|
prong_node->data.switch_prong.expr);
|
||||||
|
peer_nodes[prong_i] = prong_node->data.switch_prong.expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expr_type->id == TypeTableEntryIdEnum && !else_prong) {
|
||||||
|
for (uint32_t i = 0; i < expr_type->data.enumeration.field_count; i += 1) {
|
||||||
|
if (field_use_counts[i] == 0) {
|
||||||
|
add_node_error(g, node,
|
||||||
|
buf_sprintf("enumeration value '%s' not handled in switch",
|
||||||
|
buf_ptr(expr_type->data.enumeration.fields[i].name)));
|
||||||
|
any_errors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4782,49 +4816,18 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
|
|||||||
return g->builtin_types.entry_invalid;
|
return g->builtin_types.entry_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node,
|
if (expr_val->ok) {
|
||||||
peer_nodes, peer_types, prong_count);
|
assert(const_chosen_prong_index != -1);
|
||||||
|
|
||||||
if (resolved_type->id == TypeTableEntryIdInvalid) {
|
*const_val = get_resolved_expr(peer_nodes[const_chosen_prong_index])->const_val;
|
||||||
return resolved_type;
|
const_val->ok = true;
|
||||||
|
// the target expr depends on a compile var,
|
||||||
|
// so the entire if statement does too
|
||||||
|
const_val->depends_on_compile_var = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstExprValue *expr_val = &get_resolved_expr(*expr_node)->const_val;
|
|
||||||
if (!expr_val->ok) {
|
|
||||||
return resolved_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expr_val->ok && !expr_val->depends_on_compile_var) {
|
return resolve_peer_type_compatibility(g, import, context, node, peer_nodes, peer_types, prong_count);
|
||||||
add_node_error(g, first_executing_node(*expr_node),
|
|
||||||
buf_sprintf("value is constant; unnecessary switch statement"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!expr_val->ok) {
|
|
||||||
return resolved_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
|
|
||||||
|
|
||||||
for (int prong_i = 0; prong_i < prong_count; prong_i += 1) {
|
|
||||||
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
|
|
||||||
for (int item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) {
|
|
||||||
AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
|
|
||||||
if (expr_type->id == TypeTableEntryIdEnum) {
|
|
||||||
TypeEnumField *type_enum_field = item_node->data.symbol_expr.enum_field;
|
|
||||||
if (expr_val->data.x_enum.tag == type_enum_field->value) {
|
|
||||||
*const_val = get_resolved_expr(peer_nodes[prong_i])->const_val;
|
|
||||||
const_val->ok = true;
|
|
||||||
// the target expr depends on a compile var, so the entire if statement does too
|
|
||||||
const_val->depends_on_compile_var = true;
|
|
||||||
return resolved_type;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
zig_panic("TODO determine if const exprs are equal");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zig_unreachable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
|
|||||||
@ -1584,8 +1584,8 @@ fn f(Foo: i32) {
|
|||||||
".tmp_source.zig:6:5: error: variable shadows type 'Bar'");
|
".tmp_source.zig:6:5: error: variable shadows type 'Bar'");
|
||||||
|
|
||||||
add_compile_fail_case("multiple else prongs in a switch", R"SOURCE(
|
add_compile_fail_case("multiple else prongs in a switch", R"SOURCE(
|
||||||
fn f() {
|
fn f(x: u32) {
|
||||||
const value: bool = switch (u32(111)) {
|
const value: bool = switch (x) {
|
||||||
1234 => false,
|
1234 => false,
|
||||||
else => true,
|
else => true,
|
||||||
else => true,
|
else => true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user