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...@@ -7519,33 +7519,52 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7519 IrInstruction *cur_inst = instructions[i];7519 IrInstruction *cur_inst = instructions[i];
7520 TypeTableEntry *cur_type = cur_inst->value.type;7520 TypeTableEntry *cur_type = cur_inst->value.type;
7521 TypeTableEntry *prev_type = prev_inst->value.type;7521 TypeTableEntry *prev_type = prev_inst->value.type;
7522
7522 if (type_is_invalid(cur_type)) {7523 if (type_is_invalid(cur_type)) {
7523 return cur_type;7524 return cur_type;
7524 } else if (prev_type->id == TypeTableEntryIdUnreachable) {7525 }
7526
7527 if (prev_type->id == TypeTableEntryIdUnreachable) {
7525 prev_inst = cur_inst;7528 prev_inst = cur_inst;
7526 } else if (cur_type->id == TypeTableEntryIdUnreachable) {7529 }
7530
7531 if (cur_type->id == TypeTableEntryIdUnreachable) {
7527 continue;7532 continue;
7528 } else if (prev_type->id == TypeTableEntryIdPureError) {7533 }
7534
7535 if (prev_type->id == TypeTableEntryIdPureError) {
7529 prev_inst = cur_inst;7536 prev_inst = cur_inst;
7530 continue;7537 continue;
7531 } else if (prev_type->id == TypeTableEntryIdNullLit) {7538 }
7539
7540 if (prev_type->id == TypeTableEntryIdNullLit) {
7532 prev_inst = cur_inst;7541 prev_inst = cur_inst;
7533 continue;7542 continue;
7534 } else if (cur_type->id == TypeTableEntryIdPureError) {7543 }
7544
7545 if (cur_type->id == TypeTableEntryIdPureError) {
7535 if (prev_type->id == TypeTableEntryIdArray) {7546 if (prev_type->id == TypeTableEntryIdArray) {
7536 convert_to_const_slice = true;7547 convert_to_const_slice = true;
7537 }7548 }
7538 any_are_pure_error = true;7549 any_are_pure_error = true;
7539 continue;7550 continue;
7540 } else if (cur_type->id == TypeTableEntryIdNullLit) {7551 }
7552
7553 if (cur_type->id == TypeTableEntryIdNullLit) {
7541 any_are_null = true;7554 any_are_null = true;
7542 continue;7555 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)) {
7544 continue;7559 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)) {
7546 prev_inst = cur_inst;7563 prev_inst = cur_inst;
7547 continue;7564 continue;
7548 } else if (prev_type->id == TypeTableEntryIdInt &&7565 }
7566
7567 if (prev_type->id == TypeTableEntryIdInt &&
7549 cur_type->id == TypeTableEntryIdInt &&7568 cur_type->id == TypeTableEntryIdInt &&
7550 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)7569 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
7551 {7570 {
...@@ -7553,36 +7572,52 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7553,36 +7572,52 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7553 prev_inst = cur_inst;7572 prev_inst = cur_inst;
7554 }7573 }
7555 continue;7574 continue;
7556 } else if (prev_type->id == TypeTableEntryIdFloat &&7575 }
7576
7577 if (prev_type->id == TypeTableEntryIdFloat &&
7557 cur_type->id == TypeTableEntryIdFloat)7578 cur_type->id == TypeTableEntryIdFloat)
7558 {7579 {
7559 if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {7580 if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {
7560 prev_inst = cur_inst;7581 prev_inst = cur_inst;
7561 }7582 }
7562 } else if (prev_type->id == TypeTableEntryIdErrorUnion &&7583 }
7584
7585 if (prev_type->id == TypeTableEntryIdErrorUnion &&
7563 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))7586 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
7564 {7587 {
7565 continue;7588 continue;
7566 } else if (cur_type->id == TypeTableEntryIdErrorUnion &&7589 }
7590
7591 if (cur_type->id == TypeTableEntryIdErrorUnion &&
7567 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))7592 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
7568 {7593 {
7569 prev_inst = cur_inst;7594 prev_inst = cur_inst;
7570 continue;7595 continue;
7571 } else if (prev_type->id == TypeTableEntryIdMaybe &&7596 }
7597
7598 if (prev_type->id == TypeTableEntryIdMaybe &&
7572 types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type))7599 types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type))
7573 {7600 {
7574 continue;7601 continue;
7575 } else if (cur_type->id == TypeTableEntryIdMaybe &&7602 }
7603
7604 if (cur_type->id == TypeTableEntryIdMaybe &&
7576 types_match_const_cast_only(cur_type->data.maybe.child_type, prev_type))7605 types_match_const_cast_only(cur_type->data.maybe.child_type, prev_type))
7577 {7606 {
7578 prev_inst = cur_inst;7607 prev_inst = cur_inst;
7579 continue;7608 continue;
7580 } else if (cur_type->id == TypeTableEntryIdUndefLit) {7609 }
7610
7611 if (cur_type->id == TypeTableEntryIdUndefLit) {
7581 continue;7612 continue;
7582 } else if (prev_type->id == TypeTableEntryIdUndefLit) {7613 }
7614
7615 if (prev_type->id == TypeTableEntryIdUndefLit) {
7583 prev_inst = cur_inst;7616 prev_inst = cur_inst;
7584 continue;7617 continue;
7585 } else if (prev_type->id == TypeTableEntryIdNumLitInt ||7618 }
7619
7620 if (prev_type->id == TypeTableEntryIdNumLitInt ||
7586 prev_type->id == TypeTableEntryIdNumLitFloat)7621 prev_type->id == TypeTableEntryIdNumLitFloat)
7587 {7622 {
7588 if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {7623 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...@@ -7591,7 +7626,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7591 } else {7626 } else {
7592 return ira->codegen->builtin_types.entry_invalid;7627 return ira->codegen->builtin_types.entry_invalid;
7593 }7628 }
7594 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||7629 }
7630
7631 if (cur_type->id == TypeTableEntryIdNumLitInt ||
7595 cur_type->id == TypeTableEntryIdNumLitFloat)7632 cur_type->id == TypeTableEntryIdNumLitFloat)
7596 {7633 {
7597 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {7634 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...@@ -7599,20 +7636,26 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7599 } else {7636 } else {
7600 return ira->codegen->builtin_types.entry_invalid;7637 return ira->codegen->builtin_types.entry_invalid;
7601 }7638 }
7602 } else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&7639 }
7640
7641 if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
7603 cur_type->data.array.len != prev_type->data.array.len &&7642 cur_type->data.array.len != prev_type->data.array.len &&
7604 types_match_const_cast_only(cur_type->data.array.child_type, prev_type->data.array.child_type))7643 types_match_const_cast_only(cur_type->data.array.child_type, prev_type->data.array.child_type))
7605 {7644 {
7606 convert_to_const_slice = true;7645 convert_to_const_slice = true;
7607 prev_inst = cur_inst;7646 prev_inst = cur_inst;
7608 continue;7647 continue;
7609 } else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&7648 }
7649
7650 if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
7610 cur_type->data.array.len != prev_type->data.array.len &&7651 cur_type->data.array.len != prev_type->data.array.len &&
7611 types_match_const_cast_only(prev_type->data.array.child_type, cur_type->data.array.child_type))7652 types_match_const_cast_only(prev_type->data.array.child_type, cur_type->data.array.child_type))
7612 {7653 {
7613 convert_to_const_slice = true;7654 convert_to_const_slice = true;
7614 continue;7655 continue;
7615 } else if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&7656 }
7657
7658 if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
7616 (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||7659 (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
7617 cur_type->data.array.len == 0) &&7660 cur_type->data.array.len == 0) &&
7618 types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,7661 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...@@ -7620,7 +7663,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7620 {7663 {
7621 convert_to_const_slice = false;7664 convert_to_const_slice = false;
7622 continue;7665 continue;
7623 } else if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&7666 }
7667
7668 if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
7624 (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||7669 (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
7625 prev_type->data.array.len == 0) &&7670 prev_type->data.array.len == 0) &&
7626 types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,7671 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...@@ -7629,17 +7674,40 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7629 prev_inst = cur_inst;7674 prev_inst = cur_inst;
7630 convert_to_const_slice = false;7675 convert_to_const_slice = false;
7631 continue;7676 continue;
7632 } else {7677 }
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)));
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 }
7642 }7700 }
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;
7643 }7711 }
7644 if (convert_to_const_slice) {7712 if (convert_to_const_slice) {
7645 assert(prev_inst->value.type->id == TypeTableEntryIdArray);7713 assert(prev_inst->value.type->id == TypeTableEntryIdArray);
test/cases/union.zig+1
...@@ -200,6 +200,7 @@ const Value2 = union(Letter2) { A: i32, B, C, };...@@ -200,6 +200,7 @@ const Value2 = union(Letter2) { A: i32, B, C, };
200200
201test "implicit cast union to its tag type" {201test "implicit cast union to its tag type" {
202 var x: Value2 = Letter2.B;202 var x: Value2 = Letter2.B;
203 assert(x == Letter2.B);
203 giveMeLetterB(x);204 giveMeLetterB(x);
204}205}
205fn giveMeLetterB(x: Letter2) {206fn giveMeLetterB(x: Letter2) {