| ... | @@ -19931,7 +19931,7 @@ fn coerce( | ... | @@ -19931,7 +19931,7 @@ fn coerce( |
| 19931 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :single_item; | 19931 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :single_item; |
| 19932 | switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) { | 19932 | switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) { |
| 19933 | .ok => {}, | 19933 | .ok => {}, |
| 19934 | .no_match => break :single_item, | 19934 | else => break :single_item, |
| 19935 | } | 19935 | } |
| 19936 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); | 19936 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 19937 | } | 19937 | } |
| ... | @@ -19951,7 +19951,7 @@ fn coerce( | ... | @@ -19951,7 +19951,7 @@ fn coerce( |
| 19951 | const dst_elem_type = dest_info.pointee_type; | 19951 | const dst_elem_type = dest_info.pointee_type; |
| 19952 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src)) { | 19952 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src)) { |
| 19953 | .ok => {}, | 19953 | .ok => {}, |
| 19954 | .no_match => break :src_array_ptr, | 19954 | else => break :src_array_ptr, |
| 19955 | } | 19955 | } |
| 19956 | | 19956 | |
| 19957 | switch (dest_info.size) { | 19957 | switch (dest_info.size) { |
| ... | @@ -19990,7 +19990,7 @@ fn coerce( | ... | @@ -19990,7 +19990,7 @@ fn coerce( |
| 19990 | const dst_elem_type = dest_info.pointee_type; | 19990 | const dst_elem_type = dest_info.pointee_type; |
| 19991 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) { | 19991 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) { |
| 19992 | .ok => {}, | 19992 | .ok => {}, |
| 19993 | .no_match => break :src_c_ptr, | 19993 | else => break :src_c_ptr, |
| 19994 | } | 19994 | } |
| 19995 | // TODO add safety check for null pointer | 19995 | // TODO add safety check for null pointer |
| 19996 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); | 19996 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| ... | @@ -20034,7 +20034,7 @@ fn coerce( | ... | @@ -20034,7 +20034,7 @@ fn coerce( |
| 20034 | inst_src, | 20034 | inst_src, |
| 20035 | )) { | 20035 | )) { |
| 20036 | .ok => {}, | 20036 | .ok => {}, |
| 20037 | .no_match => break :p, | 20037 | else => break :p, |
| 20038 | } | 20038 | } |
| 20039 | if (inst_info.size == .Slice) { | 20039 | if (inst_info.size == .Slice) { |
| 20040 | if (dest_info.sentinel == null or inst_info.sentinel == null or | 20040 | if (dest_info.sentinel == null or inst_info.sentinel == null or |
| ... | @@ -20124,7 +20124,7 @@ fn coerce( | ... | @@ -20124,7 +20124,7 @@ fn coerce( |
| 20124 | inst_src, | 20124 | inst_src, |
| 20125 | )) { | 20125 | )) { |
| 20126 | .ok => {}, | 20126 | .ok => {}, |
| 20127 | .no_match => break :p, | 20127 | else => break :p, |
| 20128 | } | 20128 | } |
| 20129 | | 20129 | |
| 20130 | if (dest_info.sentinel == null or inst_info.sentinel == null or | 20130 | if (dest_info.sentinel == null or inst_info.sentinel == null or |
| ... | @@ -20356,14 +20356,348 @@ fn coerce( | ... | @@ -20356,14 +20356,348 @@ fn coerce( |
| 20356 | return sema.addConstUndef(dest_ty); | 20356 | return sema.addConstUndef(dest_ty); |
| 20357 | } | 20357 | } |
| 20358 | | 20358 | |
| 20359 | return sema.fail(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) }); | 20359 | const msg = msg: { |
| | 20360 | const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) }); |
| | 20361 | errdefer msg.destroy(sema.gpa); |
| | 20362 | |
| | 20363 | try in_memory_result.report(sema, block, inst_src, msg); |
| | 20364 | break :msg msg; |
| | 20365 | }; |
| | 20366 | return sema.failWithOwnedErrorMsg(block, msg); |
| 20360 | } | 20367 | } |
| 20361 | | 20368 | |
| 20362 | const InMemoryCoercionResult = enum { | 20369 | const InMemoryCoercionResult = union(enum) { |
| 20363 | ok, | 20370 | ok, |
| 20364 | no_match, | 20371 | no_match: Pair, |
| | 20372 | int_mismatch: Int, |
| | 20373 | error_union_payload: PairAndChild, |
| | 20374 | array_len: IntPair, |
| | 20375 | array_sentinel: Sentinel, |
| | 20376 | array_elem: PairAndChild, |
| | 20377 | vector_len: IntPair, |
| | 20378 | vector_elem: PairAndChild, |
| | 20379 | optional_shape: Pair, |
| | 20380 | optional_child: PairAndChild, |
| | 20381 | from_anyerror, |
| | 20382 | missing_error: []const []const u8, |
| | 20383 | /// true if wanted is var args |
| | 20384 | fn_var_args: bool, |
| | 20385 | /// true if wanted is generic |
| | 20386 | fn_generic: bool, |
| | 20387 | fn_param_count: IntPair, |
| | 20388 | fn_param_noalias: IntPair, |
| | 20389 | fn_param_comptime: ComptimeParam, |
| | 20390 | fn_param: Param, |
| | 20391 | fn_cc: CC, |
| | 20392 | fn_return_type: PairAndChild, |
| | 20393 | ptr_child: PairAndChild, |
| | 20394 | ptr_addrspace: AddressSpace, |
| | 20395 | ptr_sentinel: Sentinel, |
| | 20396 | ptr_size: Size, |
| | 20397 | ptr_qualifiers: Qualifiers, |
| | 20398 | ptr_allowzero: Pair, |
| | 20399 | ptr_bit_range: BitRange, |
| | 20400 | ptr_alignment: IntPair, |
| | 20401 | |
| | 20402 | const Pair = struct { |
| | 20403 | actual: Type, |
| | 20404 | wanted: Type, |
| | 20405 | }; |
| | 20406 | |
| | 20407 | const PairAndChild = struct { |
| | 20408 | child: *InMemoryCoercionResult, |
| | 20409 | actual: Type, |
| | 20410 | wanted: Type, |
| | 20411 | }; |
| | 20412 | |
| | 20413 | const Param = struct { |
| | 20414 | child: *InMemoryCoercionResult, |
| | 20415 | actual: Type, |
| | 20416 | wanted: Type, |
| | 20417 | index: u64, |
| | 20418 | }; |
| | 20419 | |
| | 20420 | const ComptimeParam = struct { |
| | 20421 | index: u64, |
| | 20422 | wanted: bool, |
| | 20423 | }; |
| | 20424 | |
| | 20425 | const Sentinel = struct { |
| | 20426 | // unreachable_value indicates no sentinel |
| | 20427 | actual: Value, |
| | 20428 | wanted: Value, |
| | 20429 | ty: Type, |
| | 20430 | }; |
| | 20431 | |
| | 20432 | const Int = struct { |
| | 20433 | actual_signedness: std.builtin.Signedness, |
| | 20434 | wanted_signedness: std.builtin.Signedness, |
| | 20435 | actual_bits: u16, |
| | 20436 | wanted_bits: u16, |
| | 20437 | }; |
| | 20438 | |
| | 20439 | const IntPair = struct { |
| | 20440 | actual: u64, |
| | 20441 | wanted: u64, |
| | 20442 | }; |
| | 20443 | |
| | 20444 | const Size = struct { |
| | 20445 | actual: std.builtin.Type.Pointer.Size, |
| | 20446 | wanted: std.builtin.Type.Pointer.Size, |
| | 20447 | }; |
| | 20448 | |
| | 20449 | const Qualifiers = struct { |
| | 20450 | actual_const: bool, |
| | 20451 | wanted_const: bool, |
| | 20452 | actual_volatile: bool, |
| | 20453 | wanted_volatile: bool, |
| | 20454 | }; |
| | 20455 | |
| | 20456 | const AddressSpace = struct { |
| | 20457 | actual: std.builtin.AddressSpace, |
| | 20458 | wanted: std.builtin.AddressSpace, |
| | 20459 | }; |
| | 20460 | |
| | 20461 | const CC = struct { |
| | 20462 | actual: std.builtin.CallingConvention, |
| | 20463 | wanted: std.builtin.CallingConvention, |
| | 20464 | }; |
| | 20465 | |
| | 20466 | const BitRange = struct { |
| | 20467 | actual_host: u16, |
| | 20468 | wanted_host: u16, |
| | 20469 | actual_offset: u16, |
| | 20470 | wanted_offset: u16, |
| | 20471 | }; |
| | 20472 | |
| | 20473 | fn dupe(child: *const InMemoryCoercionResult, arena: Allocator) !*InMemoryCoercionResult { |
| | 20474 | const res = try arena.create(InMemoryCoercionResult); |
| | 20475 | res.* = child.*; |
| | 20476 | return res; |
| | 20477 | } |
| | 20478 | |
| | 20479 | fn report(res: *const InMemoryCoercionResult, sema: *Sema, block: *Block, src: LazySrcLoc, msg: *Module.ErrorMsg) !void { |
| | 20480 | var cur = res; |
| | 20481 | while (true) switch (cur.*) { |
| | 20482 | .ok => unreachable, |
| | 20483 | .no_match => |types| { |
| | 20484 | try sema.addDeclaredHereNote(msg, types.wanted); |
| | 20485 | try sema.addDeclaredHereNote(msg, types.actual); |
| | 20486 | break; |
| | 20487 | }, |
| | 20488 | .int_mismatch => |int| { |
| | 20489 | try sema.errNote(block, src, msg, "{s} {d}-bit int cannot represent all possible {s} {d}-bit values", .{ |
| | 20490 | @tagName(int.wanted_signedness), int.wanted_bits, @tagName(int.actual_signedness), int.actual_bits, |
| | 20491 | }); |
| | 20492 | break; |
| | 20493 | }, |
| | 20494 | .error_union_payload => |pair| { |
| | 20495 | try sema.errNote(block, src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{ |
| | 20496 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20497 | }); |
| | 20498 | cur = pair.child; |
| | 20499 | }, |
| | 20500 | .array_len => |lens| { |
| | 20501 | try sema.errNote(block, src, msg, "array of length {d} cannot cast into an array of length {d}", .{ |
| | 20502 | lens.actual, lens.wanted, |
| | 20503 | }); |
| | 20504 | break; |
| | 20505 | }, |
| | 20506 | .array_sentinel => |sentinel| { |
| | 20507 | if (sentinel.actual.tag() != .unreachable_value) { |
| | 20508 | try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{ |
| | 20509 | sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod), |
| | 20510 | }); |
| | 20511 | } else { |
| | 20512 | try sema.errNote(block, src, msg, "destination array requires '{}' sentinel", .{ |
| | 20513 | sentinel.wanted.fmtValue(sentinel.ty, sema.mod), |
| | 20514 | }); |
| | 20515 | } |
| | 20516 | break; |
| | 20517 | }, |
| | 20518 | .array_elem => |pair| { |
| | 20519 | try sema.errNote(block, src, msg, "array element type '{}' cannot cast into array element type '{}'", .{ |
| | 20520 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20521 | }); |
| | 20522 | cur = pair.child; |
| | 20523 | }, |
| | 20524 | .vector_len => |lens| { |
| | 20525 | try sema.errNote(block, src, msg, "vector of length {d} cannot cast into a vector of length {d}", .{ |
| | 20526 | lens.actual, lens.wanted, |
| | 20527 | }); |
| | 20528 | break; |
| | 20529 | }, |
| | 20530 | .vector_elem => |pair| { |
| | 20531 | try sema.errNote(block, src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{ |
| | 20532 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20533 | }); |
| | 20534 | cur = pair.child; |
| | 20535 | }, |
| | 20536 | .optional_shape => |pair| { |
| | 20537 | try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type '{}'", .{ |
| | 20538 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20539 | }); |
| | 20540 | break; |
| | 20541 | }, |
| | 20542 | .optional_child => |pair| { |
| | 20543 | try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{ |
| | 20544 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20545 | }); |
| | 20546 | cur = pair.child; |
| | 20547 | }, |
| | 20548 | .from_anyerror => { |
| | 20549 | try sema.errNote(block, src, msg, "global error set cannot cast into a smaller set", .{}); |
| | 20550 | break; |
| | 20551 | }, |
| | 20552 | .missing_error => |missing_errors| { |
| | 20553 | for (missing_errors) |err| { |
| | 20554 | try sema.errNote(block, src, msg, "'error.{s}' not a member of destination error set", .{err}); |
| | 20555 | } |
| | 20556 | break; |
| | 20557 | }, |
| | 20558 | .fn_var_args => |wanted_var_args| { |
| | 20559 | if (wanted_var_args) { |
| | 20560 | try sema.errNote(block, src, msg, "non-variadic function cannot cast into a variadic function", .{}); |
| | 20561 | } else { |
| | 20562 | try sema.errNote(block, src, msg, "variadic function cannot cast into a non-variadic function", .{}); |
| | 20563 | } |
| | 20564 | break; |
| | 20565 | }, |
| | 20566 | .fn_generic => |wanted_generic| { |
| | 20567 | if (wanted_generic) { |
| | 20568 | try sema.errNote(block, src, msg, "non-generic function cannot cast into a generic function", .{}); |
| | 20569 | } else { |
| | 20570 | try sema.errNote(block, src, msg, "generic function cannot cast into a non-generic function", .{}); |
| | 20571 | } |
| | 20572 | break; |
| | 20573 | }, |
| | 20574 | .fn_param_count => |lens| { |
| | 20575 | try sema.errNote(block, src, msg, "function with {d} parameters cannot cast into a function with {d} parameters", .{ |
| | 20576 | lens.actual, lens.wanted, |
| | 20577 | }); |
| | 20578 | break; |
| | 20579 | }, |
| | 20580 | .fn_param_noalias => |param| { |
| | 20581 | var index: u6 = 0; |
| | 20582 | var actual_noalias = false; |
| | 20583 | while (true) : (index += 1) { |
| | 20584 | if (param.actual << index != param.wanted << index) { |
| | 20585 | actual_noalias = (param.actual << index) == (1 << 31); |
| | 20586 | } |
| | 20587 | } |
| | 20588 | if (!actual_noalias) { |
| | 20589 | try sema.errNote(block, src, msg, "regular paramter {d} cannot cast into a noalias paramter", .{index}); |
| | 20590 | } else { |
| | 20591 | try sema.errNote(block, src, msg, "noalias paramter {d} cannot cast into a regular paramter", .{index}); |
| | 20592 | } |
| | 20593 | break; |
| | 20594 | }, |
| | 20595 | .fn_param_comptime => |param| { |
| | 20596 | if (param.wanted) { |
| | 20597 | try sema.errNote(block, src, msg, "non-comptime paramter {d} cannot cast into a comptime paramter", .{param.index}); |
| | 20598 | } else { |
| | 20599 | try sema.errNote(block, src, msg, "comptime paramter {d} cannot cast into a non-comptime paramter", .{param.index}); |
| | 20600 | } |
| | 20601 | break; |
| | 20602 | }, |
| | 20603 | .fn_param => |param| { |
| | 20604 | try sema.errNote(block, src, msg, "parameter {d} '{}' cannot cast into '{}'", .{ |
| | 20605 | param.index, param.actual.fmt(sema.mod), param.wanted.fmt(sema.mod), |
| | 20606 | }); |
| | 20607 | cur = param.child; |
| | 20608 | }, |
| | 20609 | .fn_cc => |cc| { |
| | 20610 | try sema.errNote(block, src, msg, "calling convention {s} cannot cast into calling convention {s}", .{ @tagName(cc.actual), @tagName(cc.wanted) }); |
| | 20611 | break; |
| | 20612 | }, |
| | 20613 | .fn_return_type => |pair| { |
| | 20614 | try sema.errNote(block, src, msg, "return type '{}' cannot cast into return type '{}'", .{ |
| | 20615 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20616 | }); |
| | 20617 | cur = pair.child; |
| | 20618 | }, |
| | 20619 | .ptr_child => |pair| { |
| | 20620 | try sema.errNote(block, src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{ |
| | 20621 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20622 | }); |
| | 20623 | cur = pair.child; |
| | 20624 | }, |
| | 20625 | .ptr_addrspace => |@"addrspace"| { |
| | 20626 | try sema.errNote(block, src, msg, "address space '{s}' cannot cast into address space '{s}'", .{ @tagName(@"addrspace".actual), @tagName(@"addrspace".wanted) }); |
| | 20627 | break; |
| | 20628 | }, |
| | 20629 | .ptr_sentinel => |sentinel| { |
| | 20630 | if (sentinel.actual.tag() != .unreachable_value) { |
| | 20631 | try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{ |
| | 20632 | sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod), |
| | 20633 | }); |
| | 20634 | } else { |
| | 20635 | try sema.errNote(block, src, msg, "destination pointer requires '{}' sentinel", .{ |
| | 20636 | sentinel.wanted.fmtValue(sentinel.ty, sema.mod), |
| | 20637 | }); |
| | 20638 | } |
| | 20639 | break; |
| | 20640 | }, |
| | 20641 | .ptr_size => |size| { |
| | 20642 | try sema.errNote(block, src, msg, "a {s} pointer cannot cast into a {s} pointer", .{ pointerSizeString(size.actual), pointerSizeString(size.wanted) }); |
| | 20643 | break; |
| | 20644 | }, |
| | 20645 | .ptr_qualifiers => |qualifiers| { |
| | 20646 | const ok_const = !qualifiers.actual_const or qualifiers.wanted_const; |
| | 20647 | const ok_volatile = !qualifiers.actual_volatile or qualifiers.wanted_volatile; |
| | 20648 | if (!ok_const) { |
| | 20649 | try sema.errNote(block, src, msg, "cast discards const qualifier", .{}); |
| | 20650 | } else if (!ok_volatile) { |
| | 20651 | try sema.errNote(block, src, msg, "cast discards volatile qualifier", .{}); |
| | 20652 | } |
| | 20653 | break; |
| | 20654 | }, |
| | 20655 | .ptr_allowzero => |pair| { |
| | 20656 | const wanted_allow_zero = pair.wanted.ptrAllowsZero(); |
| | 20657 | const actual_allow_zero = pair.actual.ptrAllowsZero(); |
| | 20658 | if (actual_allow_zero and !wanted_allow_zero) { |
| | 20659 | try sema.errNote(block, src, msg, "'{}' could have null values which are illegal in type '{}'", .{ |
| | 20660 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20661 | }); |
| | 20662 | } else { |
| | 20663 | try sema.errNote(block, src, msg, "mutable '{}' allows illegal null values stored to type '{}'", .{ |
| | 20664 | pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), |
| | 20665 | }); |
| | 20666 | } |
| | 20667 | break; |
| | 20668 | }, |
| | 20669 | .ptr_bit_range => |bit_range| { |
| | 20670 | if (bit_range.actual_host != bit_range.wanted_host) { |
| | 20671 | try sema.errNote(block, src, msg, "pointer host size '{}' cannot cast into pointer host size '{}'", .{ |
| | 20672 | bit_range.actual_host, bit_range.wanted_host, |
| | 20673 | }); |
| | 20674 | } |
| | 20675 | if (bit_range.actual_offset != bit_range.wanted_offset) { |
| | 20676 | try sema.errNote(block, src, msg, "pointer bit offset '{}' cannot cast into pointer bit offset '{}'", .{ |
| | 20677 | bit_range.actual_offset, bit_range.wanted_offset, |
| | 20678 | }); |
| | 20679 | } |
| | 20680 | break; |
| | 20681 | }, |
| | 20682 | .ptr_alignment => |pair| { |
| | 20683 | try sema.errNote(block, src, msg, "pointer alignment '{}' cannot cast into pointer alignment '{}'", .{ |
| | 20684 | pair.actual, pair.wanted, |
| | 20685 | }); |
| | 20686 | break; |
| | 20687 | }, |
| | 20688 | }; |
| | 20689 | } |
| 20365 | }; | 20690 | }; |
| 20366 | | 20691 | |
| | 20692 | fn pointerSizeString(size: std.builtin.Type.Pointer.Size) []const u8 { |
| | 20693 | return switch (size) { |
| | 20694 | .One => "single", |
| | 20695 | .Many => "many", |
| | 20696 | .C => "C", |
| | 20697 | .Slice => unreachable, |
| | 20698 | }; |
| | 20699 | } |
| | 20700 | |
| 20367 | /// If pointers have the same representation in runtime memory, a bitcast AIR instruction | 20701 | /// If pointers have the same representation in runtime memory, a bitcast AIR instruction |
| 20368 | /// may be used for the coercion. | 20702 | /// may be used for the coercion. |
| 20369 | /// * `const` attribute can be gained | 20703 | /// * `const` attribute can be gained |
| ... | @@ -20373,8 +20707,6 @@ const InMemoryCoercionResult = enum { | ... | @@ -20373,8 +20707,6 @@ const InMemoryCoercionResult = enum { |
| 20373 | /// * bit offset attributes must match exactly | 20707 | /// * bit offset attributes must match exactly |
| 20374 | /// * `*`/`[*]` must match exactly, but `[*c]` matches either one | 20708 | /// * `*`/`[*]` must match exactly, but `[*c]` matches either one |
| 20375 | /// * sentinel-terminated pointers can coerce into `[*]` | 20709 | /// * sentinel-terminated pointers can coerce into `[*]` |
| 20376 | /// TODO improve this function to report recursive compile errors like it does in stage1. | | |
| 20377 | /// look at the function types_match_const_cast_only | | |
| 20378 | fn coerceInMemoryAllowed( | 20710 | fn coerceInMemoryAllowed( |
| 20379 | sema: *Sema, | 20711 | sema: *Sema, |
| 20380 | block: *Block, | 20712 | block: *Block, |
| ... | @@ -20392,11 +20724,17 @@ fn coerceInMemoryAllowed( | ... | @@ -20392,11 +20724,17 @@ fn coerceInMemoryAllowed( |
| 20392 | if (dest_ty.zigTypeTag() == .Int and src_ty.zigTypeTag() == .Int) { | 20724 | if (dest_ty.zigTypeTag() == .Int and src_ty.zigTypeTag() == .Int) { |
| 20393 | const dest_info = dest_ty.intInfo(target); | 20725 | const dest_info = dest_ty.intInfo(target); |
| 20394 | const src_info = src_ty.intInfo(target); | 20726 | const src_info = src_ty.intInfo(target); |
| 20395 | if (dest_info.signedness == src_info.signedness and | 20727 | if (dest_info.signedness != src_info.signedness or |
| 20396 | dest_info.bits == src_info.bits) | 20728 | dest_info.bits != src_info.bits) |
| 20397 | { | 20729 | { |
| 20398 | return .ok; | 20730 | return InMemoryCoercionResult{ .int_mismatch = .{ |
| | 20731 | .actual_signedness = src_info.signedness, |
| | 20732 | .wanted_signedness = dest_info.signedness, |
| | 20733 | .actual_bits = src_info.bits, |
| | 20734 | .wanted_bits = dest_info.bits, |
| | 20735 | } }; |
| 20399 | } | 20736 | } |
| | 20737 | return .ok; |
| 20400 | } | 20738 | } |
| 20401 | | 20739 | |
| 20402 | // Differently-named floats with the same number of bits. | 20740 | // Differently-named floats with the same number of bits. |
| ... | @@ -20434,9 +20772,15 @@ fn coerceInMemoryAllowed( | ... | @@ -20434,9 +20772,15 @@ fn coerceInMemoryAllowed( |
| 20434 | | 20772 | |
| 20435 | // Error Unions | 20773 | // Error Unions |
| 20436 | if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) { | 20774 | if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) { |
| 20437 | const child = try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionPayload(), src_ty.errorUnionPayload(), dest_is_mut, target, dest_src, src_src); | 20775 | const dest_payload = dest_ty.errorUnionPayload(); |
| 20438 | if (child == .no_match) { | 20776 | const src_payload = src_ty.errorUnionPayload(); |
| 20439 | return child; | 20777 | const child = try sema.coerceInMemoryAllowed(block, dest_payload, src_payload, dest_is_mut, target, dest_src, src_src); |
| | 20778 | if (child != .ok) { |
| | 20779 | return InMemoryCoercionResult{ .error_union_payload = .{ |
| | 20780 | .child = try child.dupe(sema.arena), |
| | 20781 | .actual = src_payload, |
| | 20782 | .wanted = dest_payload, |
| | 20783 | } }; |
| 20440 | } | 20784 | } |
| 20441 | return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(), src_ty.errorUnionSet(), dest_is_mut, target, dest_src, src_src); | 20785 | return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(), src_ty.errorUnionSet(), dest_is_mut, target, dest_src, src_src); |
| 20442 | } | 20786 | } |
| ... | @@ -20447,57 +20791,89 @@ fn coerceInMemoryAllowed( | ... | @@ -20447,57 +20791,89 @@ fn coerceInMemoryAllowed( |
| 20447 | } | 20791 | } |
| 20448 | | 20792 | |
| 20449 | // Arrays | 20793 | // Arrays |
| 20450 | if (dest_tag == .Array and src_tag == .Array) arrays: { | 20794 | if (dest_tag == .Array and src_tag == .Array) { |
| 20451 | const dest_info = dest_ty.arrayInfo(); | 20795 | const dest_info = dest_ty.arrayInfo(); |
| 20452 | const src_info = src_ty.arrayInfo(); | 20796 | const src_info = src_ty.arrayInfo(); |
| 20453 | if (dest_info.len != src_info.len) break :arrays; | 20797 | if (dest_info.len != src_info.len) { |
| | 20798 | return InMemoryCoercionResult{ .array_len = .{ |
| | 20799 | .actual = src_info.len, |
| | 20800 | .wanted = dest_info.len, |
| | 20801 | } }; |
| | 20802 | } |
| 20454 | | 20803 | |
| 20455 | const child = try sema.coerceInMemoryAllowed(block, dest_info.elem_type, src_info.elem_type, dest_is_mut, target, dest_src, src_src); | 20804 | const child = try sema.coerceInMemoryAllowed(block, dest_info.elem_type, src_info.elem_type, dest_is_mut, target, dest_src, src_src); |
| 20456 | if (child == .no_match) { | 20805 | if (child != .ok) { |
| 20457 | return child; | 20806 | return InMemoryCoercionResult{ .array_elem = .{ |
| | 20807 | .child = try child.dupe(sema.arena), |
| | 20808 | .actual = src_info.elem_type, |
| | 20809 | .wanted = dest_info.elem_type, |
| | 20810 | } }; |
| 20458 | } | 20811 | } |
| 20459 | const ok_sent = dest_info.sentinel == null or | 20812 | const ok_sent = dest_info.sentinel == null or |
| 20460 | (src_info.sentinel != null and | 20813 | (src_info.sentinel != null and |
| 20461 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, sema.mod)); | 20814 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, sema.mod)); |
| 20462 | if (!ok_sent) { | 20815 | if (!ok_sent) { |
| 20463 | return .no_match; | 20816 | return InMemoryCoercionResult{ .array_sentinel = .{ |
| | 20817 | .actual = src_info.sentinel orelse Value.initTag(.unreachable_value), |
| | 20818 | .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value), |
| | 20819 | .ty = dest_info.elem_type, |
| | 20820 | } }; |
| 20464 | } | 20821 | } |
| 20465 | return .ok; | 20822 | return .ok; |
| 20466 | } | 20823 | } |
| 20467 | | 20824 | |
| 20468 | // Vectors | 20825 | // Vectors |
| 20469 | if (dest_tag == .Vector and src_tag == .Vector) vectors: { | 20826 | if (dest_tag == .Vector and src_tag == .Vector) { |
| 20470 | const dest_len = dest_ty.vectorLen(); | 20827 | const dest_len = dest_ty.vectorLen(); |
| 20471 | const src_len = src_ty.vectorLen(); | 20828 | const src_len = src_ty.vectorLen(); |
| 20472 | if (dest_len != src_len) break :vectors; | 20829 | if (dest_len != src_len) { |
| | 20830 | return InMemoryCoercionResult{ .vector_len = .{ |
| | 20831 | .actual = src_len, |
| | 20832 | .wanted = dest_len, |
| | 20833 | } }; |
| | 20834 | } |
| 20473 | | 20835 | |
| 20474 | const dest_elem_ty = dest_ty.scalarType(); | 20836 | const dest_elem_ty = dest_ty.scalarType(); |
| 20475 | const src_elem_ty = src_ty.scalarType(); | 20837 | const src_elem_ty = src_ty.scalarType(); |
| 20476 | const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src); | 20838 | const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src); |
| 20477 | if (child == .no_match) break :vectors; | 20839 | if (child != .ok) { |
| | 20840 | return InMemoryCoercionResult{ .vector_elem = .{ |
| | 20841 | .child = try child.dupe(sema.arena), |
| | 20842 | .actual = src_elem_ty, |
| | 20843 | .wanted = dest_elem_ty, |
| | 20844 | } }; |
| | 20845 | } |
| 20478 | | 20846 | |
| 20479 | return .ok; | 20847 | return .ok; |
| 20480 | } | 20848 | } |
| 20481 | | 20849 | |
| 20482 | // Optionals | 20850 | // Optionals |
| 20483 | if (dest_tag == .Optional and src_tag == .Optional) optionals: { | 20851 | if (dest_tag == .Optional and src_tag == .Optional) { |
| 20484 | if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) { | 20852 | if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) { |
| 20485 | // TODO "optional type child '{}' cannot cast into optional type '{}'" | 20853 | return InMemoryCoercionResult{ .optional_shape = .{ |
| 20486 | return .no_match; | 20854 | .actual = src_ty, |
| | 20855 | .wanted = dest_ty, |
| | 20856 | } }; |
| 20487 | } | 20857 | } |
| 20488 | const dest_child_type = dest_ty.optionalChild(&dest_buf); | 20858 | const dest_child_type = dest_ty.optionalChild(&dest_buf); |
| 20489 | const src_child_type = src_ty.optionalChild(&src_buf); | 20859 | const src_child_type = src_ty.optionalChild(&src_buf); |
| 20490 | | 20860 | |
| 20491 | const child = try sema.coerceInMemoryAllowed(block, dest_child_type, src_child_type, dest_is_mut, target, dest_src, src_src); | 20861 | const child = try sema.coerceInMemoryAllowed(block, dest_child_type, src_child_type, dest_is_mut, target, dest_src, src_src); |
| 20492 | if (child == .no_match) { | 20862 | if (child != .ok) { |
| 20493 | // TODO "optional type child '{}' cannot cast into optional type child '{}'" | 20863 | return InMemoryCoercionResult{ .optional_child = .{ |
| 20494 | break :optionals; | 20864 | .child = try child.dupe(sema.arena), |
| | 20865 | .actual = src_child_type, |
| | 20866 | .wanted = dest_child_type, |
| | 20867 | } }; |
| 20495 | } | 20868 | } |
| 20496 | | 20869 | |
| 20497 | return .ok; | 20870 | return .ok; |
| 20498 | } | 20871 | } |
| 20499 | | 20872 | |
| 20500 | return .no_match; | 20873 | return InMemoryCoercionResult{ .no_match = .{ |
| | 20874 | .actual = dest_ty, |
| | 20875 | .wanted = src_ty, |
| | 20876 | } }; |
| 20501 | } | 20877 | } |
| 20502 | | 20878 | |
| 20503 | fn coerceInMemoryAllowedErrorSets( | 20879 | fn coerceInMemoryAllowedErrorSets( |
| ... | @@ -20564,6 +20940,9 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -20564,6 +20940,9 @@ fn coerceInMemoryAllowedErrorSets( |
| 20564 | } | 20940 | } |
| 20565 | } | 20941 | } |
| 20566 | | 20942 | |
| | 20943 | var missing_error_buf = std.ArrayList([]const u8).init(sema.gpa); |
| | 20944 | defer missing_error_buf.deinit(); |
| | 20945 | |
| 20567 | switch (src_ty.tag()) { | 20946 | switch (src_ty.tag()) { |
| 20568 | .error_set_inferred => { | 20947 | .error_set_inferred => { |
| 20569 | const src_data = src_ty.castTag(.error_set_inferred).?.data; | 20948 | const src_data = src_ty.castTag(.error_set_inferred).?.data; |
| ... | @@ -20572,15 +20951,21 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -20572,15 +20951,21 @@ fn coerceInMemoryAllowedErrorSets( |
| 20572 | // src anyerror status might have changed after the resolution. | 20951 | // src anyerror status might have changed after the resolution. |
| 20573 | if (src_ty.isAnyError()) { | 20952 | if (src_ty.isAnyError()) { |
| 20574 | // dest_ty.isAnyError() == true is already checked for at this point. | 20953 | // dest_ty.isAnyError() == true is already checked for at this point. |
| 20575 | return .no_match; | 20954 | return .from_anyerror; |
| 20576 | } | 20955 | } |
| 20577 | | 20956 | |
| 20578 | for (src_data.errors.keys()) |key| { | 20957 | for (src_data.errors.keys()) |key| { |
| 20579 | if (!dest_ty.errorSetHasField(key)) { | 20958 | if (!dest_ty.errorSetHasField(key)) { |
| 20580 | return .no_match; | 20959 | try missing_error_buf.append(key); |
| 20581 | } | 20960 | } |
| 20582 | } | 20961 | } |
| 20583 | | 20962 | |
| | 20963 | if (missing_error_buf.items.len != 0) { |
| | 20964 | return InMemoryCoercionResult{ |
| | 20965 | .missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items), |
| | 20966 | }; |
| | 20967 | } |
| | 20968 | |
| 20584 | return .ok; | 20969 | return .ok; |
| 20585 | }, | 20970 | }, |
| 20586 | .error_set_single => { | 20971 | .error_set_single => { |
| ... | @@ -20588,37 +20973,52 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -20588,37 +20973,52 @@ fn coerceInMemoryAllowedErrorSets( |
| 20588 | if (dest_ty.errorSetHasField(name)) { | 20973 | if (dest_ty.errorSetHasField(name)) { |
| 20589 | return .ok; | 20974 | return .ok; |
| 20590 | } | 20975 | } |
| | 20976 | const list = try sema.arena.alloc([]const u8, 1); |
| | 20977 | list[0] = name; |
| | 20978 | return InMemoryCoercionResult{ .missing_error = list }; |
| 20591 | }, | 20979 | }, |
| 20592 | .error_set_merged => { | 20980 | .error_set_merged => { |
| 20593 | const names = src_ty.castTag(.error_set_merged).?.data.keys(); | 20981 | const names = src_ty.castTag(.error_set_merged).?.data.keys(); |
| 20594 | for (names) |name| { | 20982 | for (names) |name| { |
| 20595 | if (!dest_ty.errorSetHasField(name)) { | 20983 | if (!dest_ty.errorSetHasField(name)) { |
| 20596 | return .no_match; | 20984 | try missing_error_buf.append(name); |
| 20597 | } | 20985 | } |
| 20598 | } | 20986 | } |
| 20599 | | 20987 | |
| | 20988 | if (missing_error_buf.items.len != 0) { |
| | 20989 | return InMemoryCoercionResult{ |
| | 20990 | .missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items), |
| | 20991 | }; |
| | 20992 | } |
| | 20993 | |
| 20600 | return .ok; | 20994 | return .ok; |
| 20601 | }, | 20995 | }, |
| 20602 | .error_set => { | 20996 | .error_set => { |
| 20603 | const names = src_ty.castTag(.error_set).?.data.names.keys(); | 20997 | const names = src_ty.castTag(.error_set).?.data.names.keys(); |
| 20604 | for (names) |name| { | 20998 | for (names) |name| { |
| 20605 | if (!dest_ty.errorSetHasField(name)) { | 20999 | if (!dest_ty.errorSetHasField(name)) { |
| 20606 | return .no_match; | 21000 | try missing_error_buf.append(name); |
| 20607 | } | 21001 | } |
| 20608 | } | 21002 | } |
| 20609 | | 21003 | |
| | 21004 | if (missing_error_buf.items.len != 0) { |
| | 21005 | return InMemoryCoercionResult{ |
| | 21006 | .missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items), |
| | 21007 | }; |
| | 21008 | } |
| | 21009 | |
| 20610 | return .ok; | 21010 | return .ok; |
| 20611 | }, | 21011 | }, |
| 20612 | .anyerror => switch (dest_ty.tag()) { | 21012 | .anyerror => switch (dest_ty.tag()) { |
| 20613 | .error_set_inferred => return .no_match, // Caught by dest.isAnyError() above. | 21013 | .error_set_inferred => unreachable, // Caught by dest_ty.isAnyError() above. |
| 20614 | .error_set_single, .error_set_merged, .error_set => {}, | 21014 | .error_set_single, .error_set_merged, .error_set => return .from_anyerror, |
| 20615 | .anyerror => unreachable, // Filtered out above. | 21015 | .anyerror => unreachable, // Filtered out above. |
| 20616 | else => unreachable, | 21016 | else => unreachable, |
| 20617 | }, | 21017 | }, |
| 20618 | else => unreachable, | 21018 | else => unreachable, |
| 20619 | } | 21019 | } |
| 20620 | | 21020 | |
| 20621 | return .no_match; | 21021 | unreachable; |
| 20622 | } | 21022 | } |
| 20623 | | 21023 | |
| 20624 | fn coerceInMemoryAllowedFns( | 21024 | fn coerceInMemoryAllowedFns( |
| ... | @@ -20634,44 +21034,67 @@ fn coerceInMemoryAllowedFns( | ... | @@ -20634,44 +21034,67 @@ fn coerceInMemoryAllowedFns( |
| 20634 | const src_info = src_ty.fnInfo(); | 21034 | const src_info = src_ty.fnInfo(); |
| 20635 | | 21035 | |
| 20636 | if (dest_info.is_var_args != src_info.is_var_args) { | 21036 | if (dest_info.is_var_args != src_info.is_var_args) { |
| 20637 | return .no_match; | 21037 | return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args }; |
| 20638 | } | 21038 | } |
| 20639 | | 21039 | |
| 20640 | if (dest_info.is_generic != src_info.is_generic) { | 21040 | if (dest_info.is_generic != src_info.is_generic) { |
| 20641 | return .no_match; | 21041 | return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic }; |
| | 21042 | } |
| | 21043 | |
| | 21044 | if (dest_info.cc != src_info.cc) { |
| | 21045 | return InMemoryCoercionResult{ .fn_cc = .{ |
| | 21046 | .actual = src_info.cc, |
| | 21047 | .wanted = dest_info.cc, |
| | 21048 | } }; |
| 20642 | } | 21049 | } |
| 20643 | | 21050 | |
| 20644 | if (!src_info.return_type.isNoReturn()) { | 21051 | if (!src_info.return_type.isNoReturn()) { |
| 20645 | const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type, src_info.return_type, false, target, dest_src, src_src); | 21052 | const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type, src_info.return_type, false, target, dest_src, src_src); |
| 20646 | if (rt == .no_match) { | 21053 | if (rt != .ok) { |
| 20647 | return rt; | 21054 | return InMemoryCoercionResult{ .fn_return_type = .{ |
| | 21055 | .child = try rt.dupe(sema.arena), |
| | 21056 | .actual = src_info.return_type, |
| | 21057 | .wanted = dest_info.return_type, |
| | 21058 | } }; |
| 20648 | } | 21059 | } |
| 20649 | } | 21060 | } |
| 20650 | | 21061 | |
| 20651 | if (dest_info.param_types.len != src_info.param_types.len) { | 21062 | if (dest_info.param_types.len != src_info.param_types.len) { |
| 20652 | return .no_match; | 21063 | return InMemoryCoercionResult{ .fn_param_count = .{ |
| | 21064 | .actual = dest_info.param_types.len, |
| | 21065 | .wanted = dest_info.param_types.len, |
| | 21066 | } }; |
| | 21067 | } |
| | 21068 | |
| | 21069 | if (dest_info.noalias_bits != src_info.noalias_bits) { |
| | 21070 | return InMemoryCoercionResult{ .fn_param_noalias = .{ |
| | 21071 | .actual = dest_info.noalias_bits, |
| | 21072 | .wanted = dest_info.noalias_bits, |
| | 21073 | } }; |
| 20653 | } | 21074 | } |
| 20654 | | 21075 | |
| 20655 | for (dest_info.param_types) |dest_param_ty, i| { | 21076 | for (dest_info.param_types) |dest_param_ty, i| { |
| 20656 | const src_param_ty = src_info.param_types[i]; | 21077 | const src_param_ty = src_info.param_types[i]; |
| 20657 | | 21078 | |
| 20658 | if (dest_info.comptime_params[i] != src_info.comptime_params[i]) { | 21079 | if (dest_info.comptime_params[i] != src_info.comptime_params[i]) { |
| 20659 | return .no_match; | 21080 | return InMemoryCoercionResult{ .fn_param_comptime = .{ |
| | 21081 | .index = i, |
| | 21082 | .wanted = dest_info.comptime_params[i], |
| | 21083 | } }; |
| 20660 | } | 21084 | } |
| 20661 | | 21085 | |
| 20662 | // TODO: noalias | | |
| 20663 | | | |
| 20664 | // Note: Cast direction is reversed here. | 21086 | // Note: Cast direction is reversed here. |
| 20665 | const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src); | 21087 | const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src); |
| 20666 | if (param == .no_match) { | 21088 | if (param != .ok) { |
| 20667 | return param; | 21089 | return InMemoryCoercionResult{ .fn_param = .{ |
| | 21090 | .child = try param.dupe(sema.arena), |
| | 21091 | .actual = src_param_ty, |
| | 21092 | .wanted = dest_param_ty, |
| | 21093 | .index = i, |
| | 21094 | } }; |
| 20668 | } | 21095 | } |
| 20669 | } | 21096 | } |
| 20670 | | 21097 | |
| 20671 | if (dest_info.cc != src_info.cc) { | | |
| 20672 | return .no_match; | | |
| 20673 | } | | |
| 20674 | | | |
| 20675 | return .ok; | 21098 | return .ok; |
| 20676 | } | 21099 | } |
| 20677 | | 21100 | |
| ... | @@ -20690,26 +21113,13 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -20690,26 +21113,13 @@ fn coerceInMemoryAllowedPtrs( |
| 20690 | const dest_info = dest_ptr_ty.ptrInfo().data; | 21113 | const dest_info = dest_ptr_ty.ptrInfo().data; |
| 20691 | const src_info = src_ptr_ty.ptrInfo().data; | 21114 | const src_info = src_ptr_ty.ptrInfo().data; |
| 20692 | | 21115 | |
| 20693 | const child = try sema.coerceInMemoryAllowed(block, dest_info.pointee_type, src_info.pointee_type, dest_info.mutable, target, dest_src, src_src); | | |
| 20694 | if (child == .no_match) { | | |
| 20695 | return child; | | |
| 20696 | } | | |
| 20697 | | | |
| 20698 | if (dest_info.@"addrspace" != src_info.@"addrspace") { | | |
| 20699 | return .no_match; | | |
| 20700 | } | | |
| 20701 | | | |
| 20702 | const ok_sent = dest_info.sentinel == null or src_info.size == .C or | | |
| 20703 | (src_info.sentinel != null and | | |
| 20704 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, sema.mod)); | | |
| 20705 | if (!ok_sent) { | | |
| 20706 | return .no_match; | | |
| 20707 | } | | |
| 20708 | | | |
| 20709 | const ok_ptr_size = src_info.size == dest_info.size or | 21116 | const ok_ptr_size = src_info.size == dest_info.size or |
| 20710 | src_info.size == .C or dest_info.size == .C; | 21117 | src_info.size == .C or dest_info.size == .C; |
| 20711 | if (!ok_ptr_size) { | 21118 | if (!ok_ptr_size) { |
| 20712 | return .no_match; | 21119 | return InMemoryCoercionResult{ .ptr_size = .{ |
| | 21120 | .actual = src_info.size, |
| | 21121 | .wanted = dest_info.size, |
| | 21122 | } }; |
| 20713 | } | 21123 | } |
| 20714 | | 21124 | |
| 20715 | const ok_cv_qualifiers = | 21125 | const ok_cv_qualifiers = |
| ... | @@ -20717,7 +21127,28 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -20717,7 +21127,28 @@ fn coerceInMemoryAllowedPtrs( |
| 20717 | (!src_info.@"volatile" or dest_info.@"volatile"); | 21127 | (!src_info.@"volatile" or dest_info.@"volatile"); |
| 20718 | | 21128 | |
| 20719 | if (!ok_cv_qualifiers) { | 21129 | if (!ok_cv_qualifiers) { |
| 20720 | return .no_match; | 21130 | return InMemoryCoercionResult{ .ptr_qualifiers = .{ |
| | 21131 | .actual_const = !src_info.mutable, |
| | 21132 | .wanted_const = !dest_info.mutable, |
| | 21133 | .actual_volatile = src_info.@"volatile", |
| | 21134 | .wanted_volatile = dest_info.@"volatile", |
| | 21135 | } }; |
| | 21136 | } |
| | 21137 | |
| | 21138 | if (dest_info.@"addrspace" != src_info.@"addrspace") { |
| | 21139 | return InMemoryCoercionResult{ .ptr_addrspace = .{ |
| | 21140 | .actual = src_info.@"addrspace", |
| | 21141 | .wanted = dest_info.@"addrspace", |
| | 21142 | } }; |
| | 21143 | } |
| | 21144 | |
| | 21145 | const child = try sema.coerceInMemoryAllowed(block, dest_info.pointee_type, src_info.pointee_type, dest_info.mutable, target, dest_src, src_src); |
| | 21146 | if (child != .ok) { |
| | 21147 | return InMemoryCoercionResult{ .ptr_child = .{ |
| | 21148 | .child = try child.dupe(sema.arena), |
| | 21149 | .actual = src_info.pointee_type, |
| | 21150 | .wanted = dest_info.pointee_type, |
| | 21151 | } }; |
| 20721 | } | 21152 | } |
| 20722 | | 21153 | |
| 20723 | const dest_allow_zero = dest_ty.ptrAllowsZero(); | 21154 | const dest_allow_zero = dest_ty.ptrAllowsZero(); |
| ... | @@ -20727,13 +21158,32 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -20727,13 +21158,32 @@ fn coerceInMemoryAllowedPtrs( |
| 20727 | (src_allow_zero or !dest_is_mut)) or | 21158 | (src_allow_zero or !dest_is_mut)) or |
| 20728 | (!dest_allow_zero and !src_allow_zero); | 21159 | (!dest_allow_zero and !src_allow_zero); |
| 20729 | if (!ok_allows_zero) { | 21160 | if (!ok_allows_zero) { |
| 20730 | return .no_match; | 21161 | return InMemoryCoercionResult{ .ptr_allowzero = .{ |
| | 21162 | .actual = src_ty, |
| | 21163 | .wanted = dest_ty, |
| | 21164 | } }; |
| 20731 | } | 21165 | } |
| 20732 | | 21166 | |
| 20733 | if (src_info.host_size != dest_info.host_size or | 21167 | if (src_info.host_size != dest_info.host_size or |
| 20734 | src_info.bit_offset != dest_info.bit_offset) | 21168 | src_info.bit_offset != dest_info.bit_offset) |
| 20735 | { | 21169 | { |
| 20736 | return .no_match; | 21170 | return InMemoryCoercionResult{ .ptr_bit_range = .{ |
| | 21171 | .actual_host = src_info.host_size, |
| | 21172 | .wanted_host = dest_info.host_size, |
| | 21173 | .actual_offset = src_info.bit_offset, |
| | 21174 | .wanted_offset = dest_info.bit_offset, |
| | 21175 | } }; |
| | 21176 | } |
| | 21177 | |
| | 21178 | const ok_sent = dest_info.sentinel == null or src_info.size == .C or |
| | 21179 | (src_info.sentinel != null and |
| | 21180 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, sema.mod)); |
| | 21181 | if (!ok_sent) { |
| | 21182 | return InMemoryCoercionResult{ .ptr_sentinel = .{ |
| | 21183 | .actual = src_info.sentinel orelse Value.initTag(.unreachable_value), |
| | 21184 | .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value), |
| | 21185 | .ty = dest_info.pointee_type, |
| | 21186 | } }; |
| 20737 | } | 21187 | } |
| 20738 | | 21188 | |
| 20739 | // If both pointers have alignment 0, it means they both want ABI alignment. | 21189 | // If both pointers have alignment 0, it means they both want ABI alignment. |
| ... | @@ -20758,7 +21208,10 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -20758,7 +21208,10 @@ fn coerceInMemoryAllowedPtrs( |
| 20758 | dest_info.pointee_type.abiAlignment(target); | 21208 | dest_info.pointee_type.abiAlignment(target); |
| 20759 | | 21209 | |
| 20760 | if (dest_align > src_align) { | 21210 | if (dest_align > src_align) { |
| 20761 | return .no_match; | 21211 | return InMemoryCoercionResult{ .ptr_alignment = .{ |
| | 21212 | .actual = src_align, |
| | 21213 | .wanted = dest_align, |
| | 21214 | } }; |
| 20762 | } | 21215 | } |
| 20763 | | 21216 | |
| 20764 | break :alignment; | 21217 | break :alignment; |