| ... | ... | @@ -1233,6 +1233,10 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T |
| 1233 | 1233 | return sema.fail(block, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{ lhs_ty, rhs_ty }); |
| 1234 | 1234 | } |
| 1235 | 1235 | |
| 1236 | fn 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 | |
| 1236 | 1240 | fn failWithErrorSetCodeMissing( |
| 1237 | 1241 | sema: *Sema, |
| 1238 | 1242 | block: *Block, |
| ... | ... | @@ -4636,19 +4640,23 @@ fn zirOptionalPayload( |
| 4636 | 4640 | const src = inst_data.src(); |
| 4637 | 4641 | const operand = sema.resolveInst(inst_data.operand); |
| 4638 | 4642 | 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 | }; |
| 4645 | 4653 | |
| 4646 | 4654 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { |
| 4647 | 4655 | if (val.isNull()) { |
| 4648 | 4656 | return sema.fail(block, src, "unable to unwrap null", .{}); |
| 4649 | 4657 | } |
| 4650 | 4658 | const sub_val = val.castTag(.opt_payload).?.data; |
| 4651 | | return sema.addConstant(child_type, sub_val); |
| 4659 | return sema.addConstant(result_ty, sub_val); |
| 4652 | 4660 | } |
| 4653 | 4661 | |
| 4654 | 4662 | try sema.requireRuntimeBlock(block, src); |
| ... | ... | @@ -4656,7 +4664,7 @@ fn zirOptionalPayload( |
| 4656 | 4664 | const is_non_null = try block.addUnOp(.is_non_null, operand); |
| 4657 | 4665 | try sema.addSafetyCheck(block, is_non_null, .unwrap_null); |
| 4658 | 4666 | } |
| 4659 | | return block.addTyOp(.optional_payload, child_type, operand); |
| 4667 | return block.addTyOp(.optional_payload, result_ty, operand); |
| 4660 | 4668 | } |
| 4661 | 4669 | |
| 4662 | 4670 | /// Value in, value out |
| ... | ... | @@ -8135,11 +8143,13 @@ fn zirCmpEq( |
| 8135 | 8143 | rhs_ty_tag == .Null and lhs_ty_tag == .Optional)) |
| 8136 | 8144 | { |
| 8137 | 8145 | // 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; |
| 8139 | 8147 | return sema.analyzeIsNull(block, src, opt_operand, op == .neq); |
| 8140 | 8148 | } |
| 8141 | 8149 | 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); |
| 8143 | 8153 | } |
| 8144 | 8154 | if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) { |
| 8145 | 8155 | const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty; |
| ... | ... | @@ -13598,127 +13608,127 @@ fn resolvePeerTypes( |
| 13598 | 13608 | const candidate_ty_tag = candidate_ty.zigTypeTag(); |
| 13599 | 13609 | const chosen_ty_tag = chosen_ty.zigTypeTag(); |
| 13600 | 13610 | |
| 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, |
| 13632 | 13613 | |
| 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 | }, |
| 13685 | 13618 | |
| 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 => {}, |
| 13695 | 13704 | } |
| 13696 | 13705 | |
| 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 => { |
| 13705 | 13708 | chosen = candidate; |
| 13706 | 13709 | chosen_i = candidate_i + 1; |
| 13707 | 13710 | 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; |
| 13714 | 13714 | chosen = candidate; |
| 13715 | 13715 | chosen_i = candidate_i + 1; |
| 13716 | 13716 | 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 => {}, |
| 13722 | 13732 | } |
| 13723 | 13733 | |
| 13724 | 13734 | // At this point, we hit a compile error. We need to recover |