authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-05 21:33:24-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-05 21:33:24-05:00
logc49ee9f632dd5ee7f341e9093234f39c19a32115
tree4ea672c35b3a6fd9dcb34df401b5d002ada560cf
parent2715f6fdb8bca1c88c58dac047889711359e193b

allow union and its tag type to peer resolve to the tag type


2 files changed, 100 insertions(+), 31 deletions(-)

src/ir.cpp+99-31
......@@ -7519,33 +7519,52 @@ 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 {
......@@ -7553,36 +7572,52 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
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,7 +7626,9 @@ 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)) {
......@@ -7599,20 +7636,26 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
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,
......@@ -7620,7 +7663,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
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+1
......@@ -200,6 +200,7 @@ const Value2 = union(Letter2) { A: i32, B, C, };
200200
201201test "implicit cast union to its tag type" {
202202 var x: Value2 = Letter2.B;
203 assert(x == Letter2.B);
203204 giveMeLetterB(x);
204205}
205206fn giveMeLetterB(x: Letter2) {