| ... | @@ -1233,6 +1233,10 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T | ... | @@ -1233,6 +1233,10 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T |
| 1233 | return sema.fail(block, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{ lhs_ty, rhs_ty }); | 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 | fn failWithErrorSetCodeMissing( | 1240 | fn failWithErrorSetCodeMissing( |
| 1237 | sema: *Sema, | 1241 | sema: *Sema, |
| 1238 | block: *Block, | 1242 | block: *Block, |
| ... | @@ -4636,19 +4640,23 @@ fn zirOptionalPayload( | ... | @@ -4636,19 +4640,23 @@ fn zirOptionalPayload( |
| 4636 | const src = inst_data.src(); | 4640 | const src = inst_data.src(); |
| 4637 | const operand = sema.resolveInst(inst_data.operand); | 4641 | const operand = sema.resolveInst(inst_data.operand); |
| 4638 | const operand_ty = sema.typeOf(operand); | 4642 | const operand_ty = sema.typeOf(operand); |
| 4639 | const opt_type = operand_ty; | 4643 | const result_ty = switch (operand_ty.zigTypeTag()) { |
| 4640 | if (opt_type.zigTypeTag() != .Optional) { | 4644 | .Optional => try operand_ty.optionalChildAlloc(sema.arena), |
| 4641 | return sema.fail(block, src, "expected optional type, found {}", .{opt_type}); | 4645 | .Pointer => t: { |
| 4642 | } | 4646 | if (operand_ty.ptrSize() != .C) { |
| 4643 | | 4647 | return sema.failWithExpectedOptionalType(block, src, operand_ty); |
| 4644 | const child_type = try opt_type.optionalChildAlloc(sema.arena); | 4648 | } |
| | 4649 | break :t operand_ty; |
| | 4650 | }, |
| | 4651 | else => return sema.failWithExpectedOptionalType(block, src, operand_ty), |
| | 4652 | }; |
| 4645 | | 4653 | |
| 4646 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { | 4654 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { |
| 4647 | if (val.isNull()) { | 4655 | if (val.isNull()) { |
| 4648 | return sema.fail(block, src, "unable to unwrap null", .{}); | 4656 | return sema.fail(block, src, "unable to unwrap null", .{}); |
| 4649 | } | 4657 | } |
| 4650 | const sub_val = val.castTag(.opt_payload).?.data; | 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 | try sema.requireRuntimeBlock(block, src); | 4662 | try sema.requireRuntimeBlock(block, src); |
| ... | @@ -4656,7 +4664,7 @@ fn zirOptionalPayload( | ... | @@ -4656,7 +4664,7 @@ fn zirOptionalPayload( |
| 4656 | const is_non_null = try block.addUnOp(.is_non_null, operand); | 4664 | const is_non_null = try block.addUnOp(.is_non_null, operand); |
| 4657 | try sema.addSafetyCheck(block, is_non_null, .unwrap_null); | 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 | /// Value in, value out | 4670 | /// Value in, value out |
| ... | @@ -8135,11 +8143,13 @@ fn zirCmpEq( | ... | @@ -8135,11 +8143,13 @@ fn zirCmpEq( |
| 8135 | rhs_ty_tag == .Null and lhs_ty_tag == .Optional)) | 8143 | rhs_ty_tag == .Null and lhs_ty_tag == .Optional)) |
| 8136 | { | 8144 | { |
| 8137 | // comparing null with optionals | 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 | return sema.analyzeIsNull(block, src, opt_operand, op == .neq); | 8147 | return sema.analyzeIsNull(block, src, opt_operand, op == .neq); |
| 8140 | } | 8148 | } |
| 8141 | if (((lhs_ty_tag == .Null and rhs_ty.isCPtr()) or (rhs_ty_tag == .Null and lhs_ty.isCPtr()))) { | 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 | if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) { | 8154 | if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) { |
| 8145 | const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty; | 8155 | const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty; |
| ... | @@ -13598,127 +13608,127 @@ fn resolvePeerTypes( | ... | @@ -13598,127 +13608,127 @@ fn resolvePeerTypes( |
| 13598 | const candidate_ty_tag = candidate_ty.zigTypeTag(); | 13608 | const candidate_ty_tag = candidate_ty.zigTypeTag(); |
| 13599 | const chosen_ty_tag = chosen_ty.zigTypeTag(); | 13609 | const chosen_ty_tag = chosen_ty.zigTypeTag(); |
| 13600 | | 13610 | |
| 13601 | if (candidate_ty_tag == .NoReturn) | 13611 | switch (candidate_ty_tag) { |
| 13602 | continue; | 13612 | .NoReturn, .Undefined => 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 | } | | |
| 13632 | | 13613 | |
| 13633 | if (chosen_ty_tag == .ComptimeInt and candidate_ty.isInt()) { | 13614 | .Null => { |
| 13634 | chosen = candidate; | 13615 | any_are_null = true; |
| 13635 | chosen_i = candidate_i + 1; | 13616 | continue; |
| 13636 | continue; | 13617 | }, |
| 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 | } | | |
| 13685 | | 13618 | |
| 13686 | if (chosen_ty_tag == .Null) { | 13619 | .Int => switch (chosen_ty_tag) { |
| 13687 | any_are_null = true; | 13620 | .ComptimeInt => { |
| 13688 | chosen = candidate; | 13621 | chosen = candidate; |
| 13689 | chosen_i = candidate_i + 1; | 13622 | chosen_i = candidate_i + 1; |
| 13690 | continue; | 13623 | continue; |
| 13691 | } | 13624 | }, |
| 13692 | if (candidate_ty_tag == .Null) { | 13625 | .Int => { |
| 13693 | any_are_null = true; | 13626 | if (chosen_ty.isSignedInt() == candidate_ty.isSignedInt()) { |
| 13694 | continue; | 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) { | 13706 | switch (chosen_ty_tag) { |
| 13698 | var opt_child_buf: Type.Payload.ElemType = undefined; | 13707 | .NoReturn, .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; | | |
| 13705 | chosen = candidate; | 13708 | chosen = candidate; |
| 13706 | chosen_i = candidate_i + 1; | 13709 | chosen_i = candidate_i + 1; |
| 13707 | continue; | 13710 | continue; |
| 13708 | } | 13711 | }, |
| 13709 | } | 13712 | .Null => { |
| 13710 | if (candidate_ty_tag == .Optional) { | 13713 | any_are_null = true; |
| 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) { | | |
| 13714 | chosen = candidate; | 13714 | chosen = candidate; |
| 13715 | chosen_i = candidate_i + 1; | 13715 | chosen_i = candidate_i + 1; |
| 13716 | continue; | 13716 | continue; |
| 13717 | } | 13717 | }, |
| 13718 | if (coerceInMemoryAllowed(chosen_ty, opt_child_ty, false, target) == .ok) { | 13718 | .Optional => { |
| 13719 | any_are_null = true; | 13719 | var opt_child_buf: Type.Payload.ElemType = undefined; |
| 13720 | continue; | 13720 | const opt_child_ty = chosen_ty.optionalChild(&opt_child_buf); |
| 13721 | } | 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 | // At this point, we hit a compile error. We need to recover | 13734 | // At this point, we hit a compile error. We need to recover |