authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-24 12:06:29-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-24 12:07:14-07:00
logce65ca434584783c30c80b611e02428a26f65512
tree326dc8e23e020b55c3a2901e033bac6b37c7fd7a
parentf7b090d7076a20a614bf20cac05e5e18c06ad18a

stage2: refactor coercePeerTypes and fix C ptr cmp with null


2 files changed, 151 insertions(+), 122 deletions(-)

src/Sema.zig+131-121
......@@ -1233,6 +1233,10 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T
12331233 return sema.fail(block, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{ lhs_ty, rhs_ty });
12341234}
12351235
1236fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, optional_ty: Type) CompileError {
1237 return sema.fail(block, src, "expected optional type, found {}", .{optional_ty});
1238}
1239
12361240fn failWithErrorSetCodeMissing(
12371241 sema: *Sema,
12381242 block: *Block,
......@@ -4636,19 +4640,23 @@ fn zirOptionalPayload(
46364640 const src = inst_data.src();
46374641 const operand = sema.resolveInst(inst_data.operand);
46384642 const operand_ty = sema.typeOf(operand);
4639 const opt_type = operand_ty;
4640 if (opt_type.zigTypeTag() != .Optional) {
4641 return sema.fail(block, src, "expected optional type, found {}", .{opt_type});
4642 }
4643
4644 const child_type = try opt_type.optionalChildAlloc(sema.arena);
4643 const result_ty = switch (operand_ty.zigTypeTag()) {
4644 .Optional => try operand_ty.optionalChildAlloc(sema.arena),
4645 .Pointer => t: {
4646 if (operand_ty.ptrSize() != .C) {
4647 return sema.failWithExpectedOptionalType(block, src, operand_ty);
4648 }
4649 break :t operand_ty;
4650 },
4651 else => return sema.failWithExpectedOptionalType(block, src, operand_ty),
4652 };
46454653
46464654 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
46474655 if (val.isNull()) {
46484656 return sema.fail(block, src, "unable to unwrap null", .{});
46494657 }
46504658 const sub_val = val.castTag(.opt_payload).?.data;
4651 return sema.addConstant(child_type, sub_val);
4659 return sema.addConstant(result_ty, sub_val);
46524660 }
46534661
46544662 try sema.requireRuntimeBlock(block, src);
......@@ -4656,7 +4664,7 @@ fn zirOptionalPayload(
46564664 const is_non_null = try block.addUnOp(.is_non_null, operand);
46574665 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
46584666 }
4659 return block.addTyOp(.optional_payload, child_type, operand);
4667 return block.addTyOp(.optional_payload, result_ty, operand);
46604668}
46614669
46624670/// Value in, value out
......@@ -8135,11 +8143,13 @@ fn zirCmpEq(
81358143 rhs_ty_tag == .Null and lhs_ty_tag == .Optional))
81368144 {
81378145 // comparing null with optionals
8138 const opt_operand = if (lhs_ty_tag == .Optional) lhs else rhs;
8146 const opt_operand = if (lhs_ty_tag == .Null) rhs else lhs;
81398147 return sema.analyzeIsNull(block, src, opt_operand, op == .neq);
81408148 }
81418149 if (((lhs_ty_tag == .Null and rhs_ty.isCPtr()) or (rhs_ty_tag == .Null and lhs_ty.isCPtr()))) {
8142 return sema.fail(block, src, "TODO implement C pointer cmp", .{});
8150 // comparing null with C pointers
8151 const opt_operand = if (lhs_ty_tag == .Null) rhs else lhs;
8152 return sema.analyzeIsNull(block, src, opt_operand, op == .neq);
81438153 }
81448154 if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) {
81458155 const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty;
......@@ -13598,127 +13608,127 @@ fn resolvePeerTypes(
1359813608 const candidate_ty_tag = candidate_ty.zigTypeTag();
1359913609 const chosen_ty_tag = chosen_ty.zigTypeTag();
1360013610
13601 if (candidate_ty_tag == .NoReturn)
13602 continue;
13603 if (chosen_ty_tag == .NoReturn) {
13604 chosen = candidate;
13605 chosen_i = candidate_i + 1;
13606 continue;
13607 }
13608 if (candidate_ty_tag == .Undefined)
13609 continue;
13610 if (chosen_ty_tag == .Undefined) {
13611 chosen = candidate;
13612 chosen_i = candidate_i + 1;
13613 continue;
13614 }
13615 if (chosen_ty.isInt() and
13616 candidate_ty.isInt() and
13617 chosen_ty.isSignedInt() == candidate_ty.isSignedInt())
13618 {
13619 if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) {
13620 chosen = candidate;
13621 chosen_i = candidate_i + 1;
13622 }
13623 continue;
13624 }
13625 if (chosen_ty.isRuntimeFloat() and candidate_ty.isRuntimeFloat()) {
13626 if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) {
13627 chosen = candidate;
13628 chosen_i = candidate_i + 1;
13629 }
13630 continue;
13631 }
13611 switch (candidate_ty_tag) {
13612 .NoReturn, .Undefined => continue,
1363213613
13633 if (chosen_ty_tag == .ComptimeInt and candidate_ty.isInt()) {
13634 chosen = candidate;
13635 chosen_i = candidate_i + 1;
13636 continue;
13637 }
13638
13639 if (chosen_ty.isInt() and candidate_ty_tag == .ComptimeInt) {
13640 continue;
13641 }
13642
13643 if ((chosen_ty_tag == .ComptimeFloat or chosen_ty_tag == .ComptimeInt) and
13644 candidate_ty.isRuntimeFloat())
13645 {
13646 chosen = candidate;
13647 chosen_i = candidate_i + 1;
13648 continue;
13649 }
13650 if (chosen_ty.isRuntimeFloat() and
13651 (candidate_ty_tag == .ComptimeFloat or candidate_ty_tag == .ComptimeInt))
13652 {
13653 continue;
13654 }
13655
13656 if (chosen_ty_tag == .Enum and candidate_ty_tag == .EnumLiteral) {
13657 continue;
13658 }
13659 if (chosen_ty_tag == .EnumLiteral and candidate_ty_tag == .Enum) {
13660 chosen = candidate;
13661 chosen_i = candidate_i + 1;
13662 continue;
13663 }
13664
13665 if (chosen_ty_tag == .Pointer and chosen_ty.ptrSize() == .C and
13666 (candidate_ty_tag == .Int or candidate_ty_tag == .ComptimeInt))
13667 {
13668 continue;
13669 }
13670 if (candidate_ty_tag == .Pointer and candidate_ty.ptrSize() == .C and
13671 (chosen_ty_tag == .Int or chosen_ty_tag == .ComptimeInt))
13672 {
13673 chosen = candidate;
13674 chosen_i = candidate_i + 1;
13675 continue;
13676 }
13677
13678 if (chosen_ty_tag == .ComptimeFloat and candidate_ty_tag == .ComptimeInt)
13679 continue;
13680 if (chosen_ty_tag == .ComptimeInt and candidate_ty_tag == .ComptimeFloat) {
13681 chosen = candidate;
13682 chosen_i = candidate_i + 1;
13683 continue;
13684 }
13614 .Null => {
13615 any_are_null = true;
13616 continue;
13617 },
1368513618
13686 if (chosen_ty_tag == .Null) {
13687 any_are_null = true;
13688 chosen = candidate;
13689 chosen_i = candidate_i + 1;
13690 continue;
13691 }
13692 if (candidate_ty_tag == .Null) {
13693 any_are_null = true;
13694 continue;
13619 .Int => switch (chosen_ty_tag) {
13620 .ComptimeInt => {
13621 chosen = candidate;
13622 chosen_i = candidate_i + 1;
13623 continue;
13624 },
13625 .Int => {
13626 if (chosen_ty.isSignedInt() == candidate_ty.isSignedInt()) {
13627 if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) {
13628 chosen = candidate;
13629 chosen_i = candidate_i + 1;
13630 }
13631 continue;
13632 }
13633 },
13634 .Pointer => if (chosen_ty.ptrSize() == .C) continue,
13635 else => {},
13636 },
13637 .ComptimeInt => switch (chosen_ty_tag) {
13638 .Int, .Float, .ComptimeFloat => continue,
13639 .Pointer => if (chosen_ty.ptrSize() == .C) continue,
13640 else => {},
13641 },
13642 .Float => switch (chosen_ty_tag) {
13643 .Float => {
13644 if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) {
13645 chosen = candidate;
13646 chosen_i = candidate_i + 1;
13647 }
13648 continue;
13649 },
13650 .ComptimeFloat, .ComptimeInt => {
13651 chosen = candidate;
13652 chosen_i = candidate_i + 1;
13653 continue;
13654 },
13655 else => {},
13656 },
13657 .ComptimeFloat => switch (chosen_ty_tag) {
13658 .Float => continue,
13659 .ComptimeInt => {
13660 chosen = candidate;
13661 chosen_i = candidate_i + 1;
13662 continue;
13663 },
13664 else => {},
13665 },
13666 .Enum => switch (chosen_ty_tag) {
13667 .EnumLiteral => {
13668 chosen = candidate;
13669 chosen_i = candidate_i + 1;
13670 continue;
13671 },
13672 else => {},
13673 },
13674 .EnumLiteral => switch (chosen_ty_tag) {
13675 .Enum => continue,
13676 else => {},
13677 },
13678 .Pointer => {
13679 if (candidate_ty.ptrSize() == .C) {
13680 if (chosen_ty_tag == .Int or chosen_ty_tag == .ComptimeInt) {
13681 chosen = candidate;
13682 chosen_i = candidate_i + 1;
13683 continue;
13684 }
13685 if (chosen_ty_tag == .Pointer and chosen_ty.ptrSize() != .Slice) {
13686 continue;
13687 }
13688 }
13689 },
13690 .Optional => {
13691 var opt_child_buf: Type.Payload.ElemType = undefined;
13692 const opt_child_ty = candidate_ty.optionalChild(&opt_child_buf);
13693 if (coerceInMemoryAllowed(opt_child_ty, chosen_ty, false, target) == .ok) {
13694 chosen = candidate;
13695 chosen_i = candidate_i + 1;
13696 continue;
13697 }
13698 if (coerceInMemoryAllowed(chosen_ty, opt_child_ty, false, target) == .ok) {
13699 any_are_null = true;
13700 continue;
13701 }
13702 },
13703 else => {},
1369513704 }
1369613705
13697 if (chosen_ty_tag == .Optional) {
13698 var opt_child_buf: Type.Payload.ElemType = undefined;
13699 const opt_child_ty = chosen_ty.optionalChild(&opt_child_buf);
13700 if (coerceInMemoryAllowed(opt_child_ty, candidate_ty, false, target) == .ok) {
13701 continue;
13702 }
13703 if (coerceInMemoryAllowed(candidate_ty, opt_child_ty, false, target) == .ok) {
13704 any_are_null = true;
13706 switch (chosen_ty_tag) {
13707 .NoReturn, .Undefined => {
1370513708 chosen = candidate;
1370613709 chosen_i = candidate_i + 1;
1370713710 continue;
13708 }
13709 }
13710 if (candidate_ty_tag == .Optional) {
13711 var opt_child_buf: Type.Payload.ElemType = undefined;
13712 const opt_child_ty = candidate_ty.optionalChild(&opt_child_buf);
13713 if (coerceInMemoryAllowed(opt_child_ty, chosen_ty, false, target) == .ok) {
13711 },
13712 .Null => {
13713 any_are_null = true;
1371413714 chosen = candidate;
1371513715 chosen_i = candidate_i + 1;
1371613716 continue;
13717 }
13718 if (coerceInMemoryAllowed(chosen_ty, opt_child_ty, false, target) == .ok) {
13719 any_are_null = true;
13720 continue;
13721 }
13717 },
13718 .Optional => {
13719 var opt_child_buf: Type.Payload.ElemType = undefined;
13720 const opt_child_ty = chosen_ty.optionalChild(&opt_child_buf);
13721 if (coerceInMemoryAllowed(opt_child_ty, candidate_ty, false, target) == .ok) {
13722 continue;
13723 }
13724 if (coerceInMemoryAllowed(candidate_ty, opt_child_ty, false, target) == .ok) {
13725 any_are_null = true;
13726 chosen = candidate;
13727 chosen_i = candidate_i + 1;
13728 continue;
13729 }
13730 },
13731 else => {},
1372213732 }
1372313733
1372413734 // At this point, we hit a compile error. We need to recover
src/value.zig+20-1
......@@ -1790,12 +1790,31 @@ pub const Value = extern union {
17901790 return self.tag() == .undef;
17911791 }
17921792
1793 /// Valid for all types. Asserts the value is not undefined and not unreachable.
1793 /// Asserts the value is not undefined and not unreachable.
1794 /// Integer value 0 is considered null because of C pointers.
17941795 pub fn isNull(self: Value) bool {
17951796 return switch (self.tag()) {
17961797 .null_value => true,
17971798 .opt_payload => false,
17981799
1800 // If it's not one of those two tags then it must be a C pointer value,
1801 // in which case the value 0 is null and other values are non-null.
1802
1803 .zero,
1804 .bool_false,
1805 .the_only_possible_value,
1806 => true,
1807
1808 .one,
1809 .bool_true,
1810 => false,
1811
1812 .int_u64,
1813 .int_i64,
1814 .int_big_positive,
1815 .int_big_negative,
1816 => compareWithZero(self, .eq),
1817
17991818 .undef => unreachable,
18001819 .unreachable_value => unreachable,
18011820 .inferred_alloc => unreachable,