Skip to content

Commit c49ee9f

Browse files
committedDec 6, 2017
allow union and its tag type to peer resolve to the tag type
·
0.15.20.2.0
1 parent 2715f6f commit c49ee9f

File tree

2 files changed

+100
-31
lines changed

2 files changed

+100
-31
lines changed
 

‎src/ir.cpp‎

Lines changed: 99 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7519,70 +7519,105 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
75197519
IrInstruction *cur_inst = instructions[i];
75207520
TypeTableEntry *cur_type = cur_inst->value.type;
75217521
TypeTableEntry *prev_type = prev_inst->value.type;
7522+
75227523
if (type_is_invalid(cur_type)) {
75237524
return cur_type;
7524-
} else if (prev_type->id == TypeTableEntryIdUnreachable) {
7525+
}
7526+
7527+
if (prev_type->id == TypeTableEntryIdUnreachable) {
75257528
prev_inst = cur_inst;
7526-
} else if (cur_type->id == TypeTableEntryIdUnreachable) {
7529+
}
7530+
7531+
if (cur_type->id == TypeTableEntryIdUnreachable) {
75277532
continue;
7528-
} else if (prev_type->id == TypeTableEntryIdPureError) {
7533+
}
7534+
7535+
if (prev_type->id == TypeTableEntryIdPureError) {
75297536
prev_inst = cur_inst;
75307537
continue;
7531-
} else if (prev_type->id == TypeTableEntryIdNullLit) {
7538+
}
7539+
7540+
if (prev_type->id == TypeTableEntryIdNullLit) {
75327541
prev_inst = cur_inst;
75337542
continue;
7534-
} else if (cur_type->id == TypeTableEntryIdPureError) {
7543+
}
7544+
7545+
if (cur_type->id == TypeTableEntryIdPureError) {
75357546
if (prev_type->id == TypeTableEntryIdArray) {
75367547
convert_to_const_slice = true;
75377548
}
75387549
any_are_pure_error = true;
75397550
continue;
7540-
} else if (cur_type->id == TypeTableEntryIdNullLit) {
7551+
}
7552+
7553+
if (cur_type->id == TypeTableEntryIdNullLit) {
75417554
any_are_null = true;
75427555
continue;
7543-
} else if (types_match_const_cast_only(prev_type, cur_type)) {
7556+
}
7557+
7558+
if (types_match_const_cast_only(prev_type, cur_type)) {
75447559
continue;
7545-
} else if (types_match_const_cast_only(cur_type, prev_type)) {
7560+
}
7561+
7562+
if (types_match_const_cast_only(cur_type, prev_type)) {
75467563
prev_inst = cur_inst;
75477564
continue;
7548-
} else if (prev_type->id == TypeTableEntryIdInt &&
7565+
}
7566+
7567+
if (prev_type->id == TypeTableEntryIdInt &&
75497568
cur_type->id == TypeTableEntryIdInt &&
75507569
prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
75517570
{
75527571
if (cur_type->data.integral.bit_count > prev_type->data.integral.bit_count) {
75537572
prev_inst = cur_inst;
75547573
}
75557574
continue;
7556-
} else if (prev_type->id == TypeTableEntryIdFloat &&
7575+
}
7576+
7577+
if (prev_type->id == TypeTableEntryIdFloat &&
75577578
cur_type->id == TypeTableEntryIdFloat)
75587579
{
75597580
if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {
75607581
prev_inst = cur_inst;
75617582
}
7562-
} else if (prev_type->id == TypeTableEntryIdErrorUnion &&
7583+
}
7584+
7585+
if (prev_type->id == TypeTableEntryIdErrorUnion &&
75637586
types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
75647587
{
75657588
continue;
7566-
} else if (cur_type->id == TypeTableEntryIdErrorUnion &&
7589+
}
7590+
7591+
if (cur_type->id == TypeTableEntryIdErrorUnion &&
75677592
types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
75687593
{
75697594
prev_inst = cur_inst;
75707595
continue;
7571-
} else if (prev_type->id == TypeTableEntryIdMaybe &&
7596+
}
7597+
7598+
if (prev_type->id == TypeTableEntryIdMaybe &&
75727599
types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type))
75737600
{
75747601
continue;
7575-
} else if (cur_type->id == TypeTableEntryIdMaybe &&
7602+
}
7603+
7604+
if (cur_type->id == TypeTableEntryIdMaybe &&
75767605
types_match_const_cast_only(cur_type->data.maybe.child_type, prev_type))
75777606
{
75787607
prev_inst = cur_inst;
75797608
continue;
7580-
} else if (cur_type->id == TypeTableEntryIdUndefLit) {
7609+
}
7610+
7611+
if (cur_type->id == TypeTableEntryIdUndefLit) {
75817612
continue;
7582-
} else if (prev_type->id == TypeTableEntryIdUndefLit) {
7613+
}
7614+
7615+
if (prev_type->id == TypeTableEntryIdUndefLit) {
75837616
prev_inst = cur_inst;
75847617
continue;
7585-
} else if (prev_type->id == TypeTableEntryIdNumLitInt ||
7618+
}
7619+
7620+
if (prev_type->id == TypeTableEntryIdNumLitInt ||
75867621
prev_type->id == TypeTableEntryIdNumLitFloat)
75877622
{
75887623
if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {
@@ -7591,36 +7626,46 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
75917626
} else {
75927627
return ira->codegen->builtin_types.entry_invalid;
75937628
}
7594-
} else if (cur_type->id == TypeTableEntryIdNumLitInt ||
7629+
}
7630+
7631+
if (cur_type->id == TypeTableEntryIdNumLitInt ||
75957632
cur_type->id == TypeTableEntryIdNumLitFloat)
75967633
{
75977634
if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {
75987635
continue;
75997636
} else {
76007637
return ira->codegen->builtin_types.entry_invalid;
76017638
}
7602-
} else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
7639+
}
7640+
7641+
if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
76037642
cur_type->data.array.len != prev_type->data.array.len &&
76047643
types_match_const_cast_only(cur_type->data.array.child_type, prev_type->data.array.child_type))
76057644
{
76067645
convert_to_const_slice = true;
76077646
prev_inst = cur_inst;
76087647
continue;
7609-
} else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
7648+
}
7649+
7650+
if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
76107651
cur_type->data.array.len != prev_type->data.array.len &&
76117652
types_match_const_cast_only(prev_type->data.array.child_type, cur_type->data.array.child_type))
76127653
{
76137654
convert_to_const_slice = true;
76147655
continue;
7615-
} else if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
7656+
}
7657+
7658+
if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
76167659
(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
76177660
cur_type->data.array.len == 0) &&
76187661
types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
76197662
cur_type->data.array.child_type))
76207663
{
76217664
convert_to_const_slice = false;
76227665
continue;
7623-
} else if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
7666+
}
7667+
7668+
if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
76247669
(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
76257670
prev_type->data.array.len == 0) &&
76267671
types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
@@ -7629,17 +7674,40 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
76297674
prev_inst = cur_inst;
76307675
convert_to_const_slice = false;
76317676
continue;
7632-
} else {
7633-
ErrorMsg *msg = ir_add_error_node(ira, source_node,
7634-
buf_sprintf("incompatible types: '%s' and '%s'",
7635-
buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
7636-
add_error_note(ira->codegen, msg, prev_inst->source_node,
7637-
buf_sprintf("type '%s' here", buf_ptr(&prev_type->name)));
7638-
add_error_note(ira->codegen, msg, cur_inst->source_node,
7639-
buf_sprintf("type '%s' here", buf_ptr(&cur_type->name)));
7677+
}
76407678

7641-
return ira->codegen->builtin_types.entry_invalid;
7679+
if (prev_type->id == TypeTableEntryIdEnum && cur_type->id == TypeTableEntryIdUnion &&
7680+
(cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7681+
{
7682+
type_ensure_zero_bits_known(ira->codegen, cur_type);
7683+
if (type_is_invalid(cur_type))
7684+
return ira->codegen->builtin_types.entry_invalid;
7685+
if (cur_type->data.unionation.tag_type == prev_type) {
7686+
continue;
7687+
}
7688+
}
7689+
7690+
if (cur_type->id == TypeTableEntryIdEnum && prev_type->id == TypeTableEntryIdUnion &&
7691+
(prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7692+
{
7693+
type_ensure_zero_bits_known(ira->codegen, prev_type);
7694+
if (type_is_invalid(prev_type))
7695+
return ira->codegen->builtin_types.entry_invalid;
7696+
if (prev_type->data.unionation.tag_type == cur_type) {
7697+
prev_inst = cur_inst;
7698+
continue;
7699+
}
76427700
}
7701+
7702+
ErrorMsg *msg = ir_add_error_node(ira, source_node,
7703+
buf_sprintf("incompatible types: '%s' and '%s'",
7704+
buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
7705+
add_error_note(ira->codegen, msg, prev_inst->source_node,
7706+
buf_sprintf("type '%s' here", buf_ptr(&prev_type->name)));
7707+
add_error_note(ira->codegen, msg, cur_inst->source_node,
7708+
buf_sprintf("type '%s' here", buf_ptr(&cur_type->name)));
7709+
7710+
return ira->codegen->builtin_types.entry_invalid;
76437711
}
76447712
if (convert_to_const_slice) {
76457713
assert(prev_inst->value.type->id == TypeTableEntryIdArray);

‎test/cases/union.zig‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ const Value2 = union(Letter2) { A: i32, B, C, };
200200

201201
test "implicit cast union to its tag type" {
202202
var x: Value2 = Letter2.B;
203+
assert(x == Letter2.B);
203204
giveMeLetterB(x);
204205
}
205206
fn giveMeLetterB(x: Letter2) {

0 commit comments

Comments
 (0)
Please sign in to comment.