authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-07 20:54:10+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-10 23:15:17+03:00
logb9f01bc39452042be1609b63f3066cfcac82f273
tree5db2748bb4a8f7fafc1d9c375d205b05fd391d1e
parentb9ed07227832a10e5a18667d6c7cbdffd2018da7

Sema: add detailed error notes to `coerceInMemoryAllowed`


34 files changed, 699 insertions(+), 226 deletions(-)

src/Sema.zig+526-73
......@@ -19931,7 +19931,7 @@ fn coerce(
1993119931 if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :single_item;
1993219932 switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {
1993319933 .ok => {},
19934 .no_match => break :single_item,
19934 else => break :single_item,
1993519935 }
1993619936 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
1993719937 }
......@@ -19951,7 +19951,7 @@ fn coerce(
1995119951 const dst_elem_type = dest_info.pointee_type;
1995219952 switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src)) {
1995319953 .ok => {},
19954 .no_match => break :src_array_ptr,
19954 else => break :src_array_ptr,
1995519955 }
1995619956
1995719957 switch (dest_info.size) {
......@@ -19990,7 +19990,7 @@ fn coerce(
1999019990 const dst_elem_type = dest_info.pointee_type;
1999119991 switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {
1999219992 .ok => {},
19993 .no_match => break :src_c_ptr,
19993 else => break :src_c_ptr,
1999419994 }
1999519995 // TODO add safety check for null pointer
1999619996 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
......@@ -20034,7 +20034,7 @@ fn coerce(
2003420034 inst_src,
2003520035 )) {
2003620036 .ok => {},
20037 .no_match => break :p,
20037 else => break :p,
2003820038 }
2003920039 if (inst_info.size == .Slice) {
2004020040 if (dest_info.sentinel == null or inst_info.sentinel == null or
......@@ -20124,7 +20124,7 @@ fn coerce(
2012420124 inst_src,
2012520125 )) {
2012620126 .ok => {},
20127 .no_match => break :p,
20127 else => break :p,
2012820128 }
2012920129
2013020130 if (dest_info.sentinel == null or inst_info.sentinel == null or
......@@ -20356,14 +20356,348 @@ fn coerce(
2035620356 return sema.addConstUndef(dest_ty);
2035720357 }
2035820358
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);
2036020367}
2036120368
20362const InMemoryCoercionResult = enum {
20369const InMemoryCoercionResult = union(enum) {
2036320370 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 }
2036520690};
2036620691
20692fn 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
2036720701/// If pointers have the same representation in runtime memory, a bitcast AIR instruction
2036820702/// may be used for the coercion.
2036920703/// * `const` attribute can be gained
......@@ -20373,8 +20707,6 @@ const InMemoryCoercionResult = enum {
2037320707/// * bit offset attributes must match exactly
2037420708/// * `*`/`[*]` must match exactly, but `[*c]` matches either one
2037520709/// * 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
2037820710fn coerceInMemoryAllowed(
2037920711 sema: *Sema,
2038020712 block: *Block,
......@@ -20392,11 +20724,17 @@ fn coerceInMemoryAllowed(
2039220724 if (dest_ty.zigTypeTag() == .Int and src_ty.zigTypeTag() == .Int) {
2039320725 const dest_info = dest_ty.intInfo(target);
2039420726 const src_info = src_ty.intInfo(target);
20395 if (dest_info.signedness == src_info.signedness and
20396 dest_info.bits == src_info.bits)
20727 if (dest_info.signedness != src_info.signedness or
20728 dest_info.bits != src_info.bits)
2039720729 {
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 } };
2039920736 }
20737 return .ok;
2040020738 }
2040120739
2040220740 // Differently-named floats with the same number of bits.
......@@ -20434,9 +20772,15 @@ fn coerceInMemoryAllowed(
2043420772
2043520773 // Error Unions
2043620774 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);
20438 if (child == .no_match) {
20439 return child;
20775 const dest_payload = dest_ty.errorUnionPayload();
20776 const src_payload = src_ty.errorUnionPayload();
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 } };
2044020784 }
2044120785 return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(), src_ty.errorUnionSet(), dest_is_mut, target, dest_src, src_src);
2044220786 }
......@@ -20447,57 +20791,89 @@ fn coerceInMemoryAllowed(
2044720791 }
2044820792
2044920793 // Arrays
20450 if (dest_tag == .Array and src_tag == .Array) arrays: {
20794 if (dest_tag == .Array and src_tag == .Array) {
2045120795 const dest_info = dest_ty.arrayInfo();
2045220796 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 }
2045420803
2045520804 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) {
20457 return child;
20805 if (child != .ok) {
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 } };
2045820811 }
2045920812 const ok_sent = dest_info.sentinel == null or
2046020813 (src_info.sentinel != null and
2046120814 dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, sema.mod));
2046220815 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 } };
2046420821 }
2046520822 return .ok;
2046620823 }
2046720824
2046820825 // Vectors
20469 if (dest_tag == .Vector and src_tag == .Vector) vectors: {
20826 if (dest_tag == .Vector and src_tag == .Vector) {
2047020827 const dest_len = dest_ty.vectorLen();
2047120828 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 }
2047320835
2047420836 const dest_elem_ty = dest_ty.scalarType();
2047520837 const src_elem_ty = src_ty.scalarType();
2047620838 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 }
2047820846
2047920847 return .ok;
2048020848 }
2048120849
2048220850 // Optionals
20483 if (dest_tag == .Optional and src_tag == .Optional) optionals: {
20851 if (dest_tag == .Optional and src_tag == .Optional) {
2048420852 if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) {
20485 // TODO "optional type child '{}' cannot cast into optional type '{}'"
20486 return .no_match;
20853 return InMemoryCoercionResult{ .optional_shape = .{
20854 .actual = src_ty,
20855 .wanted = dest_ty,
20856 } };
2048720857 }
2048820858 const dest_child_type = dest_ty.optionalChild(&dest_buf);
2048920859 const src_child_type = src_ty.optionalChild(&src_buf);
2049020860
2049120861 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) {
20493 // TODO "optional type child '{}' cannot cast into optional type child '{}'"
20494 break :optionals;
20862 if (child != .ok) {
20863 return InMemoryCoercionResult{ .optional_child = .{
20864 .child = try child.dupe(sema.arena),
20865 .actual = src_child_type,
20866 .wanted = dest_child_type,
20867 } };
2049520868 }
2049620869
2049720870 return .ok;
2049820871 }
2049920872
20500 return .no_match;
20873 return InMemoryCoercionResult{ .no_match = .{
20874 .actual = dest_ty,
20875 .wanted = src_ty,
20876 } };
2050120877}
2050220878
2050320879fn coerceInMemoryAllowedErrorSets(
......@@ -20564,6 +20940,9 @@ fn coerceInMemoryAllowedErrorSets(
2056420940 }
2056520941 }
2056620942
20943 var missing_error_buf = std.ArrayList([]const u8).init(sema.gpa);
20944 defer missing_error_buf.deinit();
20945
2056720946 switch (src_ty.tag()) {
2056820947 .error_set_inferred => {
2056920948 const src_data = src_ty.castTag(.error_set_inferred).?.data;
......@@ -20572,15 +20951,21 @@ fn coerceInMemoryAllowedErrorSets(
2057220951 // src anyerror status might have changed after the resolution.
2057320952 if (src_ty.isAnyError()) {
2057420953 // dest_ty.isAnyError() == true is already checked for at this point.
20575 return .no_match;
20954 return .from_anyerror;
2057620955 }
2057720956
2057820957 for (src_data.errors.keys()) |key| {
2057920958 if (!dest_ty.errorSetHasField(key)) {
20580 return .no_match;
20959 try missing_error_buf.append(key);
2058120960 }
2058220961 }
2058320962
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
2058420969 return .ok;
2058520970 },
2058620971 .error_set_single => {
......@@ -20588,37 +20973,52 @@ fn coerceInMemoryAllowedErrorSets(
2058820973 if (dest_ty.errorSetHasField(name)) {
2058920974 return .ok;
2059020975 }
20976 const list = try sema.arena.alloc([]const u8, 1);
20977 list[0] = name;
20978 return InMemoryCoercionResult{ .missing_error = list };
2059120979 },
2059220980 .error_set_merged => {
2059320981 const names = src_ty.castTag(.error_set_merged).?.data.keys();
2059420982 for (names) |name| {
2059520983 if (!dest_ty.errorSetHasField(name)) {
20596 return .no_match;
20984 try missing_error_buf.append(name);
2059720985 }
2059820986 }
2059920987
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
2060020994 return .ok;
2060120995 },
2060220996 .error_set => {
2060320997 const names = src_ty.castTag(.error_set).?.data.names.keys();
2060420998 for (names) |name| {
2060520999 if (!dest_ty.errorSetHasField(name)) {
20606 return .no_match;
21000 try missing_error_buf.append(name);
2060721001 }
2060821002 }
2060921003
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
2061021010 return .ok;
2061121011 },
2061221012 .anyerror => switch (dest_ty.tag()) {
20613 .error_set_inferred => return .no_match, // Caught by dest.isAnyError() above.
20614 .error_set_single, .error_set_merged, .error_set => {},
21013 .error_set_inferred => unreachable, // Caught by dest_ty.isAnyError() above.
21014 .error_set_single, .error_set_merged, .error_set => return .from_anyerror,
2061521015 .anyerror => unreachable, // Filtered out above.
2061621016 else => unreachable,
2061721017 },
2061821018 else => unreachable,
2061921019 }
2062021020
20621 return .no_match;
21021 unreachable;
2062221022}
2062321023
2062421024fn coerceInMemoryAllowedFns(
......@@ -20634,44 +21034,67 @@ fn coerceInMemoryAllowedFns(
2063421034 const src_info = src_ty.fnInfo();
2063521035
2063621036 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 };
2063821038 }
2063921039
2064021040 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 } };
2064221049 }
2064321050
2064421051 if (!src_info.return_type.isNoReturn()) {
2064521052 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) {
20647 return rt;
21053 if (rt != .ok) {
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 } };
2064821059 }
2064921060 }
2065021061
2065121062 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 } };
2065321074 }
2065421075
2065521076 for (dest_info.param_types) |dest_param_ty, i| {
2065621077 const src_param_ty = src_info.param_types[i];
2065721078
2065821079 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 } };
2066021084 }
2066121085
20662 // TODO: noalias
20663
2066421086 // Note: Cast direction is reversed here.
2066521087 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src);
20666 if (param == .no_match) {
20667 return param;
21088 if (param != .ok) {
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 } };
2066821095 }
2066921096 }
2067021097
20671 if (dest_info.cc != src_info.cc) {
20672 return .no_match;
20673 }
20674
2067521098 return .ok;
2067621099}
2067721100
......@@ -20690,26 +21113,13 @@ fn coerceInMemoryAllowedPtrs(
2069021113 const dest_info = dest_ptr_ty.ptrInfo().data;
2069121114 const src_info = src_ptr_ty.ptrInfo().data;
2069221115
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
2070921116 const ok_ptr_size = src_info.size == dest_info.size or
2071021117 src_info.size == .C or dest_info.size == .C;
2071121118 if (!ok_ptr_size) {
20712 return .no_match;
21119 return InMemoryCoercionResult{ .ptr_size = .{
21120 .actual = src_info.size,
21121 .wanted = dest_info.size,
21122 } };
2071321123 }
2071421124
2071521125 const ok_cv_qualifiers =
......@@ -20717,7 +21127,28 @@ fn coerceInMemoryAllowedPtrs(
2071721127 (!src_info.@"volatile" or dest_info.@"volatile");
2071821128
2071921129 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 } };
2072121152 }
2072221153
2072321154 const dest_allow_zero = dest_ty.ptrAllowsZero();
......@@ -20727,13 +21158,32 @@ fn coerceInMemoryAllowedPtrs(
2072721158 (src_allow_zero or !dest_is_mut)) or
2072821159 (!dest_allow_zero and !src_allow_zero);
2072921160 if (!ok_allows_zero) {
20730 return .no_match;
21161 return InMemoryCoercionResult{ .ptr_allowzero = .{
21162 .actual = src_ty,
21163 .wanted = dest_ty,
21164 } };
2073121165 }
2073221166
2073321167 if (src_info.host_size != dest_info.host_size or
2073421168 src_info.bit_offset != dest_info.bit_offset)
2073521169 {
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 } };
2073721187 }
2073821188
2073921189 // If both pointers have alignment 0, it means they both want ABI alignment.
......@@ -20758,7 +21208,10 @@ fn coerceInMemoryAllowedPtrs(
2075821208 dest_info.pointee_type.abiAlignment(target);
2075921209
2076021210 if (dest_align > src_align) {
20761 return .no_match;
21211 return InMemoryCoercionResult{ .ptr_alignment = .{
21212 .actual = src_align,
21213 .wanted = dest_align,
21214 } };
2076221215 }
2076321216
2076421217 break :alignment;
test/cases/compile_errors/address_of_number_literal.zig+1
......@@ -8,3 +8,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }
88// target=native
99//
1010// :3:30: error: expected type '*const i32', found '*const comptime_int'
11// :3:30: note: pointer type child 'comptime_int' cannot cast into pointer type child 'i32'
test/cases/compile_errors/attempted_implicit_cast_from_const_T_to_array_len_1_T.zig created+14
......@@ -0,0 +1,14 @@
1export fn entry(byte: u8) void {
2 const w: i32 = 1234;
3 var x: *const i32 = &w;
4 var y: *[1]i32 = x;
5 y[0] += 1;
6 _ = byte;
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :4:22: error: expected type '*[1]i32', found '*const i32'
14// :4:22: note: cast discards const qualifier
test/cases/compile_errors/cast_error_union_of_global_error_set_to_error_union_of_smaller_error_set.zig created+15
......@@ -0,0 +1,15 @@
1const SmallErrorSet = error{A};
2export fn entry() void {
3 var x: SmallErrorSet!i32 = foo();
4 _ = x;
5}
6fn foo() anyerror!i32 {
7 return error.B;
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :3:35: error: expected type 'error{A}!i32', found 'anyerror!i32'
15// :3:35: note: global error set cannot cast into a smaller set
test/cases/compile_errors/cast_global_error_set_to_error_set.zig created+15
......@@ -0,0 +1,15 @@
1const SmallErrorSet = error{A};
2export fn entry() void {
3 var x: SmallErrorSet = foo();
4 _ = x;
5}
6fn foo() anyerror {
7 return error.B;
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :3:31: error: expected type 'error{A}', found 'anyerror'
15// :3:31: note: global error set cannot cast into a smaller set
test/cases/compile_errors/casting_bit_offset_pointer_to_regular_pointer.zig+2
......@@ -19,3 +19,5 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }
1919// target=native
2020//
2121// :8:15: error: expected type '*const u3', found '*align(0:3:1) const u3'
22// :8:15: note: pointer host size '1' cannot cast into pointer host size '0'
23// :8:15: note: pointer bit offset '3' cannot cast into pointer bit offset '0'
test/cases/compile_errors/dont_implicit_cast_double_pointer_to_anyopaque.zig+1
......@@ -11,3 +11,4 @@ export fn entry() void {
1111// target=native
1212//
1313// :5:28: error: expected type '*anyopaque', found '**u32'
14// :5:28: note: pointer type child '*u32' cannot cast into pointer type child 'anyopaque'
test/cases/compile_errors/error_note_for_function_parameter_incompatibility.zig created+13
......@@ -0,0 +1,13 @@
1fn do_the_thing(func: *const fn (arg: i32) void) void { _ = func; }
2fn bar(arg: bool) void { _ = arg; }
3export fn entry() void {
4 do_the_thing(bar);
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :4:17: error: expected type '*const fn(i32) void', found '*const fn(bool) void'
12// :4:17: note: pointer type child 'fn(bool) void' cannot cast into pointer type child 'fn(i32) void'
13// :4:17: note: parameter 0 'bool' cannot cast into 'i32'
test/cases/compile_errors/implicit_cast_of_error_set_not_a_subset.zig created+16
......@@ -0,0 +1,16 @@
1const Set1 = error{A, B};
2const Set2 = error{A, C};
3export fn entry() void {
4 foo(Set1.B);
5}
6fn foo(set1: Set1) void {
7 var x: Set2 = set1;
8 _ = x;
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :7:19: error: expected type 'error{A,C}', found 'error{A,B}'
16// :7:19: note: 'error.B' not a member of destination error set
test/cases/compile_errors/implicit_casting_C_pointers_which_would_mess_up_null_semantics.zig created+26
......@@ -0,0 +1,26 @@
1export fn entry() void {
2 var slice: []const u8 = "aoeu";
3 const opt_many_ptr: [*]const u8 = slice.ptr;
4 var ptr_opt_many_ptr = &opt_many_ptr;
5 var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
6 ptr_opt_many_ptr = c_ptr;
7}
8export fn entry2() void {
9 var buf: [4]u8 = "aoeu".*;
10 var slice: []u8 = &buf;
11 var opt_many_ptr: [*]u8 = slice.ptr;
12 var ptr_opt_many_ptr = &opt_many_ptr;
13 var c_ptr: [*c][*c]const u8 = ptr_opt_many_ptr;
14 _ = c_ptr;
15}
16
17// error
18// backend=stage2
19// target=native
20//
21// :6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]const u8'
22// :6:24: note: pointer type child '[*c]const u8' cannot cast into pointer type child '[*]const u8'
23// :6:24: note: '[*c]const u8' could have null values which are illegal in type '[*]const u8'
24// :13:35: error: expected type '[*c][*c]const u8', found '*[*]u8'
25// :13:35: note: pointer type child '[*]u8' cannot cast into pointer type child '[*c]const u8'
26// :13:35: note: mutable '[*]u8' allows illegal null values stored to type '[*c]const u8'
test/cases/compile_errors/implicitly_casting_enum_to_tag_type.zig+1
......@@ -15,3 +15,4 @@ export fn entry() void {
1515// target=native
1616//
1717// :9:22: error: expected type 'u2', found 'tmp.Small'
18// :1:15: note: enum declared here
test/cases/compile_errors/incompatible_sentinels.zig created+29
......@@ -0,0 +1,29 @@
1// Note: One of the error messages here is backwards. It would be nice to fix, but that's not
2// going to stop me from merging this branch which fixes a bunch of other stuff.
3export fn entry1(ptr: [*:255]u8) [*:0]u8 {
4 return ptr;
5}
6export fn entry2(ptr: [*]u8) [*:0]u8 {
7 return ptr;
8}
9export fn entry3() void {
10 var array: [2:0]u8 = [_:255]u8{ 1, 2 };
11 _ = array;
12}
13export fn entry4() void {
14 var array: [2:0]u8 = [_]u8{ 1, 2 };
15 _ = array;
16}
17
18// error
19// backend=stage2
20// target=native
21//
22// :4:12: error: expected type '[*:0]u8', found '[*:255]u8'
23// :4:12: note: pointer sentinel '255' cannot cast into pointer sentinel '0'
24// :7:12: error: expected type '[*:0]u8', found '[*]u8'
25// :7:12: note: destination pointer requires '0' sentinel
26// :10:35: error: expected type '[2:0]u8', found '[2:255]u8'
27// :10:35: note: array sentinel '255' cannot cast into array sentinel '0'
28// :14:31: error: expected type '[2:0]u8', found '[2]u8'
29// :14:31: note: destination array requires '0' sentinel
test/cases/compile_errors/incorrect_return_type.zig+2
......@@ -19,3 +19,5 @@
1919// target=native
2020//
2121// :8:16: error: expected type 'tmp.A', found 'tmp.B'
22// :10:12: note: struct declared here
23// :4:12: note: struct declared here
test/cases/compile_errors/invalid_address_space_coercion.zig+1
......@@ -11,3 +11,4 @@ pub fn main() void {
1111// target=x86_64-linux,x86_64-macos
1212//
1313// :2:12: error: expected type '*i32', found '*addrspace(.gs) i32'
14// :2:12: note: address space 'gs' cannot cast into address space 'generic'
test/cases/compile_errors/invalid_cast_from_integral_type_to_enum.zig+1
......@@ -15,3 +15,4 @@ fn foo(x: usize) void {
1515// target=native
1616//
1717// :9:10: error: expected type 'usize', found 'tmp.E'
18// :1:11: note: enum declared here
test/cases/compile_errors/invalid_pointer_keeps_address_space_when_taking_address_of_dereference.zig+1
......@@ -11,3 +11,4 @@ pub fn main() void {
1111// target=x86_64-linux,x86_64-macos
1212//
1313// :2:12: error: expected type '*i32', found '*addrspace(.gs) i32'
14// :2:12: note: address space 'gs' cannot cast into address space 'generic'
test/cases/compile_errors/not_an_enum_type.zig+1
......@@ -17,3 +17,4 @@ const ExpectedVarDeclOrFn = struct {};
1717// target=native
1818//
1919// :4:9: error: expected type '@typeInfo(tmp.Error).Union.tag_type.?', found 'type'
20// :8:1: note: enum declared here
test/cases/compile_errors/passing_a_not-aligned-enough_pointer_to_cmpxchg.zig+1
......@@ -10,3 +10,4 @@ export fn entry() bool {
1010// target=native
1111//
1212// :4:31: error: expected type '*i32', found '*align(1) i32'
13// :4:31: note: pointer alignment '1' cannot cast into pointer alignment '4'
test/cases/compile_errors/pointer_with_different_address_spaces.zig+1
......@@ -11,3 +11,4 @@ export fn entry2() void {
1111// target=x86_64-linux,x86_64-macos
1212//
1313// :2:12: error: expected type '*addrspace(.fs) i32', found '*addrspace(.gs) i32'
14// :2:12: note: address space 'gs' cannot cast into address space 'fs'
test/cases/compile_errors/pointers_with_different_address_spaces.zig+1
......@@ -11,3 +11,4 @@ pub fn main() void {
1111// target=x86_64-linux,x86_64-macos
1212//
1313// :2:13: error: expected type '*i32', found '*addrspace(.gs) i32'
14// :2:13: note: address space 'gs' cannot cast into address space 'generic'
test/cases/compile_errors/shifting_RHS_is_log2_of_LHS_int_bit_width.zig+1
......@@ -7,3 +7,4 @@ export fn entry(x: u8, y: u8) u8 {
77// target=native
88//
99// :2:17: error: expected type 'u3', found 'u8'
10// :2:17: note: unsigned 3-bit int cannot represent all possible unsigned 8-bit values
test/cases/compile_errors/slice_sentinel_mismatch-2.zig created+12
......@@ -0,0 +1,12 @@
1fn foo() [:0]u8 {
2 var x: []u8 = undefined;
3 return x;
4}
5comptime { _ = foo; }
6
7// error
8// backend=stage2
9// target=native
10//
11// :3:12: error: expected type '[:0]u8', found '[]u8'
12// :3:12: note: destination pointer requires '0' sentinel
test/cases/compile_errors/stage1/obj/attempted_implicit_cast_from_const_T_to_array_len_1_T.zig deleted-14
......@@ -1,14 +0,0 @@
1export fn entry(byte: u8) void {
2 const w: i32 = 1234;
3 var x: *const i32 = &w;
4 var y: *[1]i32 = x;
5 y[0] += 1;
6 _ = byte;
7}
8
9// error
10// backend=stage1
11// target=native
12//
13// tmp.zig:4:22: error: expected type '*[1]i32', found '*const i32'
14// tmp.zig:4:22: note: cast discards const qualifier
test/cases/compile_errors/stage1/obj/cast_error_union_of_global_error_set_to_error_union_of_smaller_error_set.zig deleted-16
......@@ -1,16 +0,0 @@
1const SmallErrorSet = error{A};
2export fn entry() void {
3 var x: SmallErrorSet!i32 = foo();
4 _ = x;
5}
6fn foo() anyerror!i32 {
7 return error.B;
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:3:35: error: expected type 'SmallErrorSet!i32', found 'anyerror!i32'
15// tmp.zig:3:35: note: error set 'anyerror' cannot cast into error set 'SmallErrorSet'
16// tmp.zig:3:35: note: cannot cast global error set into smaller set
test/cases/compile_errors/stage1/obj/cast_global_error_set_to_error_set.zig deleted-15
......@@ -1,15 +0,0 @@
1const SmallErrorSet = error{A};
2export fn entry() void {
3 var x: SmallErrorSet = foo();
4 _ = x;
5}
6fn foo() anyerror {
7 return error.B;
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:3:31: error: expected type 'SmallErrorSet', found 'anyerror'
15// tmp.zig:3:31: note: cannot cast global error set into smaller set
test/cases/compile_errors/stage1/obj/error_note_for_function_parameter_incompatibility.zig deleted-12
......@@ -1,12 +0,0 @@
1fn do_the_thing(func: fn (arg: i32) void) void { _ = func; }
2fn bar(arg: bool) void { _ = arg; }
3export fn entry() void {
4 do_the_thing(bar);
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:4:18: error: expected type 'fn(i32) void', found 'fn(bool) void
12// tmp.zig:4:18: note: parameter 0: 'bool' cannot cast into 'i32'
test/cases/compile_errors/stage1/obj/implicit_cast_of_error_set_not_a_subset.zig deleted-16
......@@ -1,16 +0,0 @@
1const Set1 = error{A, B};
2const Set2 = error{A, C};
3export fn entry() void {
4 foo(Set1.B);
5}
6fn foo(set1: Set1) void {
7 var x: Set2 = set1;
8 _ = x;
9}
10
11// error
12// backend=stage1
13// target=native
14//
15// tmp.zig:7:19: error: expected type 'Set2', found 'Set1'
16// tmp.zig:1:23: note: 'error.B' not a member of destination error set
test/cases/compile_errors/stage1/obj/implicit_casting_C_pointers_which_would_mess_up_null_semantics.zig deleted-26
......@@ -1,26 +0,0 @@
1export fn entry() void {
2 var slice: []const u8 = "aoeu";
3 const opt_many_ptr: [*]const u8 = slice.ptr;
4 var ptr_opt_many_ptr = &opt_many_ptr;
5 var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
6 ptr_opt_many_ptr = c_ptr;
7}
8export fn entry2() void {
9 var buf: [4]u8 = "aoeu".*;
10 var slice: []u8 = &buf;
11 var opt_many_ptr: [*]u8 = slice.ptr;
12 var ptr_opt_many_ptr = &opt_many_ptr;
13 var c_ptr: [*c][*c]const u8 = ptr_opt_many_ptr;
14 _ = c_ptr;
15}
16
17// error
18// backend=stage1
19// target=native
20//
21// tmp.zig:6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]const u8'
22// tmp.zig:6:24: note: pointer type child '[*c]const u8' cannot cast into pointer type child '[*]const u8'
23// tmp.zig:6:24: note: '[*c]const u8' could have null values which are illegal in type '[*]const u8'
24// tmp.zig:13:35: error: expected type '[*c][*c]const u8', found '*[*]u8'
25// tmp.zig:13:35: note: pointer type child '[*]u8' cannot cast into pointer type child '[*c]const u8'
26// tmp.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'
test/cases/compile_errors/stage1/obj/incompatible_sentinels.zig deleted-29
......@@ -1,29 +0,0 @@
1// Note: One of the error messages here is backwards. It would be nice to fix, but that's not
2// going to stop me from merging this branch which fixes a bunch of other stuff.
3export fn entry1(ptr: [*:255]u8) [*:0]u8 {
4 return ptr;
5}
6export fn entry2(ptr: [*]u8) [*:0]u8 {
7 return ptr;
8}
9export fn entry3() void {
10 var array: [2:0]u8 = [_:255]u8{ 1, 2 };
11 _ = array;
12}
13export fn entry4() void {
14 var array: [2:0]u8 = [_]u8{ 1, 2 };
15 _ = array;
16}
17
18// error
19// backend=stage1
20// target=native
21//
22// tmp.zig:4:12: error: expected type '[*:0]u8', found '[*:255]u8'
23// tmp.zig:4:12: note: destination pointer requires a terminating '0' sentinel, but source pointer has a terminating '255' sentinel
24// tmp.zig:7:12: error: expected type '[*:0]u8', found '[*]u8'
25// tmp.zig:7:12: note: destination pointer requires a terminating '0' sentinel
26// tmp.zig:10:35: error: expected type '[2:255]u8', found '[2:0]u8'
27// tmp.zig:10:35: note: destination array requires a terminating '255' sentinel, but source array has a terminating '0' sentinel
28// tmp.zig:14:31: error: expected type '[2:0]u8', found '[2]u8'
29// tmp.zig:14:31: note: destination array requires a terminating '0' sentinel
test/cases/compile_errors/stage1/obj/slice_sentinel_mismatch-2.zig deleted-12
......@@ -1,12 +0,0 @@
1fn foo() [:0]u8 {
2 var x: []u8 = undefined;
3 return x;
4}
5comptime { _ = foo; }
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:3:12: error: expected type '[:0]u8', found '[]u8'
12// tmp.zig:3:12: note: destination pointer requires a terminating '0' sentinel
test/cases/compile_errors/stage1/obj/type_checking_function_pointers.zig deleted-13
......@@ -1,13 +0,0 @@
1fn a(b: fn (*const u8) void) void {
2 b('a');
3}
4fn c(d: u8) void {_ = d;}
5export fn entry() void {
6 a(c);
7}
8
9// error
10// backend=stage1
11// target=native
12//
13// tmp.zig:6:7: error: expected type 'fn(*const u8) void', found 'fn(u8) void'
test/cases/compile_errors/type_checking_function_pointers.zig created+15
......@@ -0,0 +1,15 @@
1fn a(b: *const fn (*const u8) void) void {
2 _ = b;
3}
4fn c(d: u8) void {_ = d;}
5export fn entry() void {
6 a(c);
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :6:6: error: expected type '*const fn(*const u8) void', found '*const fn(u8) void'
14// :6:6: note: pointer type child 'fn(u8) void' cannot cast into pointer type child 'fn(*const u8) void'
15// :6:6: note: parameter 0 'u8' cannot cast into '*const u8'
test/cases/compile_errors/type_mismatch_in_C_prototype_with_varargs.zig+2
......@@ -11,3 +11,5 @@ export fn main() void {
1111// target=native
1212//
1313// :5:22: error: expected type 'fn([*c]u8, ...) callconv(.C) void', found 'fn([*:0]u8, ...) callconv(.C) void'
14// :5:22: note: parameter 0 '[*:0]u8' cannot cast into '[*c]u8'
15// :5:22: note: '[*c]u8' could have null values which are illegal in type '[*:0]u8'
test/cases/compile_errors/wrong_type_for_reify_type.zig+1
......@@ -7,3 +7,4 @@ export fn entry() void {
77// target=native
88//
99// :2:15: error: expected type 'builtin.Type', found 'comptime_int'
10// :?:?: note: union declared here