mirror of
https://github.com/ziglang/zig.git
synced 2025-12-18 04:03:14 +00:00
Merge pull request #14477 from Vexu/fixes
Improve `@ptrCast` errors, fix some bugs
This commit is contained in:
commit
6b7ad22981
@ -8809,6 +8809,15 @@ pub const PrefetchOptions = struct {
|
|||||||
{#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#}
|
{#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#}
|
||||||
to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}.
|
to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
{#syntax#}@ptrCast{#endsyntax#} cannot be used for:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Removing {#syntax#}const{#endsyntax#} or {#syntax#}volatile{#endsyntax#} qualifier, use {#link|@qualCast#}.</li>
|
||||||
|
<li>Changing pointer address space, use {#link|@addrSpaceCast#}.</li>
|
||||||
|
<li>Increasing pointer alignment, use {#link|@alignCast#}.</li>
|
||||||
|
<li>Casting a non-slice pointer to a slice, use slicing syntax {#syntax#}ptr[start..end]{#endsyntax#}.</li>
|
||||||
|
</ul>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@ptrToInt#}
|
{#header_open|@ptrToInt#}
|
||||||
@ -8821,6 +8830,13 @@ pub const PrefetchOptions = struct {
|
|||||||
|
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
|
{#header_open|@qualCast#}
|
||||||
|
<pre>{#syntax#}@qualCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
Remove {#syntax#}const{#endsyntax#} or {#syntax#}volatile{#endsyntax#} qualifier from a pointer.
|
||||||
|
</p>
|
||||||
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@rem#}
|
{#header_open|@rem#}
|
||||||
<pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
|
<pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@ -1164,7 +1164,7 @@ fn windowsCreateProcessPathExt(
|
|||||||
var app_name_unicode_string = windows.UNICODE_STRING{
|
var app_name_unicode_string = windows.UNICODE_STRING{
|
||||||
.Length = app_name_len_bytes,
|
.Length = app_name_len_bytes,
|
||||||
.MaximumLength = app_name_len_bytes,
|
.MaximumLength = app_name_len_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(app_name_wildcard.ptr)),
|
.Buffer = @qualCast([*:0]u16, app_name_wildcard.ptr),
|
||||||
};
|
};
|
||||||
const rc = windows.ntdll.NtQueryDirectoryFile(
|
const rc = windows.ntdll.NtQueryDirectoryFile(
|
||||||
dir.fd,
|
dir.fd,
|
||||||
@ -1261,7 +1261,7 @@ fn windowsCreateProcessPathExt(
|
|||||||
var app_name_unicode_string = windows.UNICODE_STRING{
|
var app_name_unicode_string = windows.UNICODE_STRING{
|
||||||
.Length = app_name_len_bytes,
|
.Length = app_name_len_bytes,
|
||||||
.MaximumLength = app_name_len_bytes,
|
.MaximumLength = app_name_len_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(app_name_appended.ptr)),
|
.Buffer = @qualCast([*:0]u16, app_name_appended.ptr),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Re-use the directory handle but this time we call with the appended app name
|
// Re-use the directory handle but this time we call with the appended app name
|
||||||
|
|||||||
@ -1763,7 +1763,7 @@ pub const Dir = struct {
|
|||||||
var nt_name = w.UNICODE_STRING{
|
var nt_name = w.UNICODE_STRING{
|
||||||
.Length = path_len_bytes,
|
.Length = path_len_bytes,
|
||||||
.MaximumLength = path_len_bytes,
|
.MaximumLength = path_len_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
|
.Buffer = @qualCast([*:0]u16, sub_path_w),
|
||||||
};
|
};
|
||||||
var attr = w.OBJECT_ATTRIBUTES{
|
var attr = w.OBJECT_ATTRIBUTES{
|
||||||
.Length = @sizeOf(w.OBJECT_ATTRIBUTES),
|
.Length = @sizeOf(w.OBJECT_ATTRIBUTES),
|
||||||
|
|||||||
@ -4513,7 +4513,7 @@ pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32
|
|||||||
var nt_name = windows.UNICODE_STRING{
|
var nt_name = windows.UNICODE_STRING{
|
||||||
.Length = path_len_bytes,
|
.Length = path_len_bytes,
|
||||||
.MaximumLength = path_len_bytes,
|
.MaximumLength = path_len_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
|
.Buffer = @qualCast([*:0]u16, sub_path_w),
|
||||||
};
|
};
|
||||||
var attr = windows.OBJECT_ATTRIBUTES{
|
var attr = windows.OBJECT_ATTRIBUTES{
|
||||||
.Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
|
.Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
|
||||||
|
|||||||
@ -85,7 +85,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
|
|||||||
var nt_name = UNICODE_STRING{
|
var nt_name = UNICODE_STRING{
|
||||||
.Length = path_len_bytes,
|
.Length = path_len_bytes,
|
||||||
.MaximumLength = path_len_bytes,
|
.MaximumLength = path_len_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w.ptr)),
|
.Buffer = @qualCast([*]u16, sub_path_w.ptr),
|
||||||
};
|
};
|
||||||
var attr = OBJECT_ATTRIBUTES{
|
var attr = OBJECT_ATTRIBUTES{
|
||||||
.Length = @sizeOf(OBJECT_ATTRIBUTES),
|
.Length = @sizeOf(OBJECT_ATTRIBUTES),
|
||||||
@ -634,7 +634,7 @@ pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void
|
|||||||
var nt_name = UNICODE_STRING{
|
var nt_name = UNICODE_STRING{
|
||||||
.Length = path_len_bytes,
|
.Length = path_len_bytes,
|
||||||
.MaximumLength = path_len_bytes,
|
.MaximumLength = path_len_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(path_name.ptr)),
|
.Buffer = @qualCast([*]u16, path_name.ptr),
|
||||||
};
|
};
|
||||||
|
|
||||||
const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);
|
const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);
|
||||||
@ -766,7 +766,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin
|
|||||||
var nt_name = UNICODE_STRING{
|
var nt_name = UNICODE_STRING{
|
||||||
.Length = path_len_bytes,
|
.Length = path_len_bytes,
|
||||||
.MaximumLength = path_len_bytes,
|
.MaximumLength = path_len_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w.ptr)),
|
.Buffer = @qualCast([*]u16, sub_path_w.ptr),
|
||||||
};
|
};
|
||||||
var attr = OBJECT_ATTRIBUTES{
|
var attr = OBJECT_ATTRIBUTES{
|
||||||
.Length = @sizeOf(OBJECT_ATTRIBUTES),
|
.Length = @sizeOf(OBJECT_ATTRIBUTES),
|
||||||
@ -876,7 +876,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
|
|||||||
.Length = path_len_bytes,
|
.Length = path_len_bytes,
|
||||||
.MaximumLength = path_len_bytes,
|
.MaximumLength = path_len_bytes,
|
||||||
// The Windows API makes this mutable, but it will not mutate here.
|
// The Windows API makes this mutable, but it will not mutate here.
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w.ptr)),
|
.Buffer = @qualCast([*]u16, sub_path_w.ptr),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
|
if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
|
||||||
@ -1414,7 +1414,7 @@ pub fn sendmsg(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 {
|
pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 {
|
||||||
var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @intToPtr([*]u8, @ptrToInt(buf)) };
|
var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @qualCast([*]u8, buf) };
|
||||||
var bytes_send: DWORD = undefined;
|
var bytes_send: DWORD = undefined;
|
||||||
if (ws2_32.WSASendTo(s, @ptrCast([*]ws2_32.WSABUF, &buffer), 1, &bytes_send, flags, to, @intCast(i32, to_len), null, null) == ws2_32.SOCKET_ERROR) {
|
if (ws2_32.WSASendTo(s, @ptrCast([*]ws2_32.WSABUF, &buffer), 1, &bytes_send, flags, to, @intCast(i32, to_len), null, null) == ws2_32.SOCKET_ERROR) {
|
||||||
return ws2_32.SOCKET_ERROR;
|
return ws2_32.SOCKET_ERROR;
|
||||||
@ -1876,13 +1876,13 @@ pub fn eqlIgnoreCaseWTF16(a: []const u16, b: []const u16) bool {
|
|||||||
const a_string = UNICODE_STRING{
|
const a_string = UNICODE_STRING{
|
||||||
.Length = a_bytes,
|
.Length = a_bytes,
|
||||||
.MaximumLength = a_bytes,
|
.MaximumLength = a_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(a.ptr)),
|
.Buffer = @qualCast([*]u16, a.ptr),
|
||||||
};
|
};
|
||||||
const b_bytes = @intCast(u16, b.len * 2);
|
const b_bytes = @intCast(u16, b.len * 2);
|
||||||
const b_string = UNICODE_STRING{
|
const b_string = UNICODE_STRING{
|
||||||
.Length = b_bytes,
|
.Length = b_bytes,
|
||||||
.MaximumLength = b_bytes,
|
.MaximumLength = b_bytes,
|
||||||
.Buffer = @intToPtr([*]u16, @ptrToInt(b.ptr)),
|
.Buffer = @qualCast([*]u16, b.ptr),
|
||||||
};
|
};
|
||||||
return ntdll.RtlEqualUnicodeString(&a_string, &b_string, TRUE) == TRUE;
|
return ntdll.RtlEqualUnicodeString(&a_string, &b_string, TRUE) == TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,7 +75,7 @@ fn castPtr(comptime DestType: type, target: anytype) DestType {
|
|||||||
const source = ptrInfo(@TypeOf(target));
|
const source = ptrInfo(@TypeOf(target));
|
||||||
|
|
||||||
if (source.is_const and !dest.is_const or source.is_volatile and !dest.is_volatile)
|
if (source.is_const and !dest.is_const or source.is_volatile and !dest.is_volatile)
|
||||||
return @intToPtr(DestType, @ptrToInt(target))
|
return @qualCast(DestType, target)
|
||||||
else if (@typeInfo(dest.child) == .Opaque)
|
else if (@typeInfo(dest.child) == .Opaque)
|
||||||
// dest.alignment would error out
|
// dest.alignment would error out
|
||||||
return @ptrCast(DestType, target)
|
return @ptrCast(DestType, target)
|
||||||
|
|||||||
@ -2530,6 +2530,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
|||||||
.bit_size_of,
|
.bit_size_of,
|
||||||
.typeof_log2_int_type,
|
.typeof_log2_int_type,
|
||||||
.ptr_to_int,
|
.ptr_to_int,
|
||||||
|
.qual_cast,
|
||||||
.align_of,
|
.align_of,
|
||||||
.bool_to_int,
|
.bool_to_int,
|
||||||
.embed_file,
|
.embed_file,
|
||||||
@ -4278,7 +4279,34 @@ fn testDecl(
|
|||||||
var num_namespaces_out: u32 = 0;
|
var num_namespaces_out: u32 = 0;
|
||||||
var capturing_namespace: ?*Scope.Namespace = null;
|
var capturing_namespace: ?*Scope.Namespace = null;
|
||||||
while (true) switch (s.tag) {
|
while (true) switch (s.tag) {
|
||||||
.local_val, .local_ptr => unreachable, // a test cannot be in a local scope
|
.local_val => {
|
||||||
|
const local_val = s.cast(Scope.LocalVal).?;
|
||||||
|
if (local_val.name == name_str_index) {
|
||||||
|
local_val.used = test_name_token;
|
||||||
|
return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
|
||||||
|
@tagName(local_val.id_cat),
|
||||||
|
}, &[_]u32{
|
||||||
|
try astgen.errNoteTok(local_val.token_src, "{s} declared here", .{
|
||||||
|
@tagName(local_val.id_cat),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
s = local_val.parent;
|
||||||
|
},
|
||||||
|
.local_ptr => {
|
||||||
|
const local_ptr = s.cast(Scope.LocalPtr).?;
|
||||||
|
if (local_ptr.name == name_str_index) {
|
||||||
|
local_ptr.used = test_name_token;
|
||||||
|
return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
|
||||||
|
@tagName(local_ptr.id_cat),
|
||||||
|
}, &[_]u32{
|
||||||
|
try astgen.errNoteTok(local_ptr.token_src, "{s} declared here", .{
|
||||||
|
@tagName(local_ptr.id_cat),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
s = local_ptr.parent;
|
||||||
|
},
|
||||||
.gen_zir => s = s.cast(GenZir).?.parent,
|
.gen_zir => s = s.cast(GenZir).?.parent,
|
||||||
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
|
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
|
||||||
.namespace, .enum_namespace => {
|
.namespace, .enum_namespace => {
|
||||||
@ -8010,6 +8038,7 @@ fn builtinCall(
|
|||||||
.float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast),
|
.float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast),
|
||||||
.int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast),
|
.int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast),
|
||||||
.ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast),
|
.ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast),
|
||||||
|
.qual_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .qual_cast),
|
||||||
.truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate),
|
.truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate),
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
||||||
@ -8692,6 +8721,7 @@ fn callExpr(
|
|||||||
defer arg_block.unstack();
|
defer arg_block.unstack();
|
||||||
|
|
||||||
// `call_inst` is reused to provide the param type.
|
// `call_inst` is reused to provide the param type.
|
||||||
|
arg_block.rl_ty_inst = call_inst;
|
||||||
const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node);
|
const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node);
|
||||||
_ = try arg_block.addBreak(.break_inline, call_index, arg_ref);
|
_ = try arg_block.addBreak(.break_inline, call_index, arg_ref);
|
||||||
|
|
||||||
@ -10840,7 +10870,12 @@ const GenZir = struct {
|
|||||||
// we emit ZIR for the block break instructions to have the result values,
|
// we emit ZIR for the block break instructions to have the result values,
|
||||||
// and then rvalue() on that to pass the value to the result location.
|
// and then rvalue() on that to pass the value to the result location.
|
||||||
switch (parent_ri.rl) {
|
switch (parent_ri.rl) {
|
||||||
.ty, .coerced_ty => |ty_inst| {
|
.coerced_ty => |ty_inst| {
|
||||||
|
// Type coercion needs to happend before breaks.
|
||||||
|
gz.rl_ty_inst = ty_inst;
|
||||||
|
gz.break_result_info = .{ .rl = .{ .ty = ty_inst } };
|
||||||
|
},
|
||||||
|
.ty => |ty_inst| {
|
||||||
gz.rl_ty_inst = ty_inst;
|
gz.rl_ty_inst = ty_inst;
|
||||||
gz.break_result_info = parent_ri;
|
gz.break_result_info = parent_ri;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -75,6 +75,7 @@ pub const Tag = enum {
|
|||||||
prefetch,
|
prefetch,
|
||||||
ptr_cast,
|
ptr_cast,
|
||||||
ptr_to_int,
|
ptr_to_int,
|
||||||
|
qual_cast,
|
||||||
rem,
|
rem,
|
||||||
return_address,
|
return_address,
|
||||||
select,
|
select,
|
||||||
@ -674,6 +675,13 @@ pub const list = list: {
|
|||||||
.param_count = 1,
|
.param_count = 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.{
|
||||||
|
"@qualCast",
|
||||||
|
.{
|
||||||
|
.tag = .qual_cast,
|
||||||
|
.param_count = 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
.{
|
.{
|
||||||
"@rem",
|
"@rem",
|
||||||
.{
|
.{
|
||||||
|
|||||||
101
src/Sema.zig
101
src/Sema.zig
@ -1015,6 +1015,7 @@ fn analyzeBodyInner(
|
|||||||
.float_cast => try sema.zirFloatCast(block, inst),
|
.float_cast => try sema.zirFloatCast(block, inst),
|
||||||
.int_cast => try sema.zirIntCast(block, inst),
|
.int_cast => try sema.zirIntCast(block, inst),
|
||||||
.ptr_cast => try sema.zirPtrCast(block, inst),
|
.ptr_cast => try sema.zirPtrCast(block, inst),
|
||||||
|
.qual_cast => try sema.zirQualCast(block, inst),
|
||||||
.truncate => try sema.zirTruncate(block, inst),
|
.truncate => try sema.zirTruncate(block, inst),
|
||||||
.align_cast => try sema.zirAlignCast(block, inst),
|
.align_cast => try sema.zirAlignCast(block, inst),
|
||||||
.has_decl => try sema.zirHasDecl(block, inst),
|
.has_decl => try sema.zirHasDecl(block, inst),
|
||||||
@ -3294,7 +3295,7 @@ fn ensureResultUsed(
|
|||||||
const msg = msg: {
|
const msg = msg: {
|
||||||
const msg = try sema.errMsg(block, src, "error is ignored", .{});
|
const msg = try sema.errMsg(block, src, "error is ignored", .{});
|
||||||
errdefer msg.destroy(sema.gpa);
|
errdefer msg.destroy(sema.gpa);
|
||||||
try sema.errNote(block, src, msg, "consider using `try`, `catch`, or `if`", .{});
|
try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{});
|
||||||
break :msg msg;
|
break :msg msg;
|
||||||
};
|
};
|
||||||
return sema.failWithOwnedErrorMsg(msg);
|
return sema.failWithOwnedErrorMsg(msg);
|
||||||
@ -3325,7 +3326,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
|
|||||||
const msg = msg: {
|
const msg = msg: {
|
||||||
const msg = try sema.errMsg(block, src, "error is discarded", .{});
|
const msg = try sema.errMsg(block, src, "error is discarded", .{});
|
||||||
errdefer msg.destroy(sema.gpa);
|
errdefer msg.destroy(sema.gpa);
|
||||||
try sema.errNote(block, src, msg, "consider using `try`, `catch`, or `if`", .{});
|
try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{});
|
||||||
break :msg msg;
|
break :msg msg;
|
||||||
};
|
};
|
||||||
return sema.failWithOwnedErrorMsg(msg);
|
return sema.failWithOwnedErrorMsg(msg);
|
||||||
@ -6874,6 +6875,8 @@ fn analyzeInlineCallArg(
|
|||||||
if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
|
if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
} else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {
|
||||||
|
_ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
|
||||||
}
|
}
|
||||||
const casted_arg = sema.coerceExtra(arg_block, param_ty, uncasted_arg, arg_src, .{ .param_src = .{
|
const casted_arg = sema.coerceExtra(arg_block, param_ty, uncasted_arg, arg_src, .{ .param_src = .{
|
||||||
.func_inst = func_inst,
|
.func_inst = func_inst,
|
||||||
@ -6947,6 +6950,9 @@ fn analyzeInlineCallArg(
|
|||||||
.val = arg_val,
|
.val = arg_val,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
if (zir_tags[inst] == .param_anytype_comptime) {
|
||||||
|
_ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
|
||||||
|
}
|
||||||
sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
|
sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8467,7 +8473,7 @@ fn handleExternLibName(
|
|||||||
return sema.fail(
|
return sema.fail(
|
||||||
block,
|
block,
|
||||||
src_loc,
|
src_loc,
|
||||||
"dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
|
"dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by '-l{s}' or '-fPIC'.",
|
||||||
.{ lib_name, lib_name },
|
.{ lib_name, lib_name },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -9004,7 +9010,18 @@ fn zirParam(
|
|||||||
if (is_comptime and sema.preallocated_new_func != null) {
|
if (is_comptime and sema.preallocated_new_func != null) {
|
||||||
// We have a comptime value for this parameter so it should be elided from the
|
// We have a comptime value for this parameter so it should be elided from the
|
||||||
// function type of the function instruction in this block.
|
// function type of the function instruction in this block.
|
||||||
const coerced_arg = try sema.coerce(block, param_ty, arg, src);
|
const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
|
||||||
|
error.NeededSourceLocation => {
|
||||||
|
// We are instantiating a generic function and a comptime arg
|
||||||
|
// cannot be coerced to the param type, but since we don't
|
||||||
|
// have the callee source location return `GenericPoison`
|
||||||
|
// so that the instantiation is failed and the coercion
|
||||||
|
// is handled by comptime call logic instead.
|
||||||
|
assert(sema.is_generic_instantiation);
|
||||||
|
return error.GenericPoison;
|
||||||
|
},
|
||||||
|
else => return err,
|
||||||
|
};
|
||||||
sema.inst_map.putAssumeCapacity(inst, coerced_arg);
|
sema.inst_map.putAssumeCapacity(inst, coerced_arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -19519,13 +19536,34 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
|||||||
const operand_info = operand_ty.ptrInfo().data;
|
const operand_info = operand_ty.ptrInfo().data;
|
||||||
const dest_info = dest_ty.ptrInfo().data;
|
const dest_info = dest_ty.ptrInfo().data;
|
||||||
if (!operand_info.mutable and dest_info.mutable) {
|
if (!operand_info.mutable and dest_info.mutable) {
|
||||||
return sema.fail(block, src, "cast discards const qualifier", .{});
|
const msg = msg: {
|
||||||
|
const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{});
|
||||||
|
errdefer msg.destroy(sema.gpa);
|
||||||
|
|
||||||
|
try sema.errNote(block, src, msg, "consider using '@qualCast'", .{});
|
||||||
|
break :msg msg;
|
||||||
|
};
|
||||||
|
return sema.failWithOwnedErrorMsg(msg);
|
||||||
}
|
}
|
||||||
if (operand_info.@"volatile" and !dest_info.@"volatile") {
|
if (operand_info.@"volatile" and !dest_info.@"volatile") {
|
||||||
return sema.fail(block, src, "cast discards volatile qualifier", .{});
|
const msg = msg: {
|
||||||
|
const msg = try sema.errMsg(block, src, "cast discards volatile qualifier", .{});
|
||||||
|
errdefer msg.destroy(sema.gpa);
|
||||||
|
|
||||||
|
try sema.errNote(block, src, msg, "consider using '@qualCast'", .{});
|
||||||
|
break :msg msg;
|
||||||
|
};
|
||||||
|
return sema.failWithOwnedErrorMsg(msg);
|
||||||
}
|
}
|
||||||
if (operand_info.@"addrspace" != dest_info.@"addrspace") {
|
if (operand_info.@"addrspace" != dest_info.@"addrspace") {
|
||||||
return sema.fail(block, src, "cast changes pointer address space", .{});
|
const msg = msg: {
|
||||||
|
const msg = try sema.errMsg(block, src, "cast changes pointer address space", .{});
|
||||||
|
errdefer msg.destroy(sema.gpa);
|
||||||
|
|
||||||
|
try sema.errNote(block, src, msg, "consider using '@addrSpaceCast'", .{});
|
||||||
|
break :msg msg;
|
||||||
|
};
|
||||||
|
return sema.failWithOwnedErrorMsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dest_is_slice = dest_ty.isSlice();
|
const dest_is_slice = dest_ty.isSlice();
|
||||||
@ -19580,6 +19618,8 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
|||||||
try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{
|
try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{
|
||||||
dest_ty.fmt(sema.mod), dest_align,
|
dest_ty.fmt(sema.mod), dest_align,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try sema.errNote(block, src, msg, "consider using '@alignCast'", .{});
|
||||||
break :msg msg;
|
break :msg msg;
|
||||||
};
|
};
|
||||||
return sema.failWithOwnedErrorMsg(msg);
|
return sema.failWithOwnedErrorMsg(msg);
|
||||||
@ -19615,6 +19655,49 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
|||||||
return block.addBitCast(aligned_dest_ty, ptr);
|
return block.addBitCast(aligned_dest_ty, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn zirQualCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||||
|
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||||
|
const src = inst_data.src();
|
||||||
|
const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||||
|
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
|
||||||
|
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||||
|
const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
|
||||||
|
const operand = try sema.resolveInst(extra.rhs);
|
||||||
|
const operand_ty = sema.typeOf(operand);
|
||||||
|
|
||||||
|
try sema.checkPtrType(block, dest_ty_src, dest_ty);
|
||||||
|
try sema.checkPtrOperand(block, operand_src, operand_ty);
|
||||||
|
|
||||||
|
var operand_payload = operand_ty.ptrInfo();
|
||||||
|
var dest_info = dest_ty.ptrInfo();
|
||||||
|
|
||||||
|
operand_payload.data.mutable = dest_info.data.mutable;
|
||||||
|
operand_payload.data.@"volatile" = dest_info.data.@"volatile";
|
||||||
|
|
||||||
|
const altered_operand_ty = Type.initPayload(&operand_payload.base);
|
||||||
|
if (!altered_operand_ty.eql(dest_ty, sema.mod)) {
|
||||||
|
const msg = msg: {
|
||||||
|
const msg = try sema.errMsg(block, src, "'@qualCast' can only modify 'const' and 'volatile' qualifiers", .{});
|
||||||
|
errdefer msg.destroy(sema.gpa);
|
||||||
|
|
||||||
|
dest_info.data.mutable = !operand_ty.isConstPtr();
|
||||||
|
dest_info.data.@"volatile" = operand_ty.isVolatilePtr();
|
||||||
|
const altered_dest_ty = Type.initPayload(&dest_info.base);
|
||||||
|
try sema.errNote(block, src, msg, "expected type '{}'", .{altered_dest_ty.fmt(sema.mod)});
|
||||||
|
try sema.errNote(block, src, msg, "got type '{}'", .{operand_ty.fmt(sema.mod)});
|
||||||
|
break :msg msg;
|
||||||
|
};
|
||||||
|
return sema.failWithOwnedErrorMsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
|
||||||
|
return sema.addConstant(dest_ty, operand_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
try sema.requireRuntimeBlock(block, src, null);
|
||||||
|
return block.addBitCast(dest_ty, operand);
|
||||||
|
}
|
||||||
|
|
||||||
fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||||
const src = inst_data.src();
|
const src = inst_data.src();
|
||||||
@ -25131,7 +25214,7 @@ fn coerceExtra(
|
|||||||
(try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
|
(try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
|
||||||
{
|
{
|
||||||
try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{});
|
try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{});
|
||||||
try sema.errNote(block, inst_src, msg, "consider using `try`, `catch`, or `if`", .{});
|
try sema.errNote(block, inst_src, msg, "consider using 'try', 'catch', or 'if'", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ?T to T
|
// ?T to T
|
||||||
@ -25140,7 +25223,7 @@ fn coerceExtra(
|
|||||||
(try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(&buf), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
|
(try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(&buf), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
|
||||||
{
|
{
|
||||||
try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{});
|
try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{});
|
||||||
try sema.errNote(block, inst_src, msg, "consider using `.?`, `orelse`, or `if`", .{});
|
try sema.errNote(block, inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
try in_memory_result.report(sema, block, inst_src, msg);
|
try in_memory_result.report(sema, block, inst_src, msg);
|
||||||
|
|||||||
@ -176,7 +176,9 @@ pub fn print(
|
|||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < max_len) : (i += 1) {
|
while (i < max_len) : (i += 1) {
|
||||||
buf[i] = std.math.cast(u8, val.fieldValue(ty, i).toUnsignedInt(target)) orelse break :str;
|
const elem = val.fieldValue(ty, i);
|
||||||
|
if (elem.isUndef()) break :str;
|
||||||
|
buf[i] = std.math.cast(u8, elem.toUnsignedInt(target)) orelse break :str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const truncated = if (len > max_string_len) " (truncated)" else "";
|
const truncated = if (len > max_string_len) " (truncated)" else "";
|
||||||
@ -390,6 +392,7 @@ pub fn print(
|
|||||||
while (i < max_len) : (i += 1) {
|
while (i < max_len) : (i += 1) {
|
||||||
var elem_buf: Value.ElemValueBuffer = undefined;
|
var elem_buf: Value.ElemValueBuffer = undefined;
|
||||||
const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf);
|
const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf);
|
||||||
|
if (elem_val.isUndef()) break :str;
|
||||||
buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(target)) orelse break :str;
|
buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(target)) orelse break :str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -857,6 +857,9 @@ pub const Inst = struct {
|
|||||||
/// Implements the `@ptrCast` builtin.
|
/// Implements the `@ptrCast` builtin.
|
||||||
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
|
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
|
||||||
ptr_cast,
|
ptr_cast,
|
||||||
|
/// Implements the `@qualCast` builtin.
|
||||||
|
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
|
||||||
|
qual_cast,
|
||||||
/// Implements the `@truncate` builtin.
|
/// Implements the `@truncate` builtin.
|
||||||
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
|
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
|
||||||
truncate,
|
truncate,
|
||||||
@ -1195,6 +1198,7 @@ pub const Inst = struct {
|
|||||||
.float_cast,
|
.float_cast,
|
||||||
.int_cast,
|
.int_cast,
|
||||||
.ptr_cast,
|
.ptr_cast,
|
||||||
|
.qual_cast,
|
||||||
.truncate,
|
.truncate,
|
||||||
.align_cast,
|
.align_cast,
|
||||||
.has_field,
|
.has_field,
|
||||||
@ -1484,6 +1488,7 @@ pub const Inst = struct {
|
|||||||
.float_cast,
|
.float_cast,
|
||||||
.int_cast,
|
.int_cast,
|
||||||
.ptr_cast,
|
.ptr_cast,
|
||||||
|
.qual_cast,
|
||||||
.truncate,
|
.truncate,
|
||||||
.align_cast,
|
.align_cast,
|
||||||
.has_field,
|
.has_field,
|
||||||
@ -1755,6 +1760,7 @@ pub const Inst = struct {
|
|||||||
.float_cast = .pl_node,
|
.float_cast = .pl_node,
|
||||||
.int_cast = .pl_node,
|
.int_cast = .pl_node,
|
||||||
.ptr_cast = .pl_node,
|
.ptr_cast = .pl_node,
|
||||||
|
.qual_cast = .pl_node,
|
||||||
.truncate = .pl_node,
|
.truncate = .pl_node,
|
||||||
.align_cast = .pl_node,
|
.align_cast = .pl_node,
|
||||||
.typeof_builtin = .pl_node,
|
.typeof_builtin = .pl_node,
|
||||||
|
|||||||
@ -332,6 +332,7 @@ const Writer = struct {
|
|||||||
.float_cast,
|
.float_cast,
|
||||||
.int_cast,
|
.int_cast,
|
||||||
.ptr_cast,
|
.ptr_cast,
|
||||||
|
.qual_cast,
|
||||||
.truncate,
|
.truncate,
|
||||||
.align_cast,
|
.align_cast,
|
||||||
.div_exact,
|
.div_exact,
|
||||||
|
|||||||
BIN
stage1/zig1.wasm
BIN
stage1/zig1.wasm
Binary file not shown.
@ -1125,3 +1125,21 @@ test "returning an opaque type from a function" {
|
|||||||
};
|
};
|
||||||
try expect(S.foo(123).b == 123);
|
try expect(S.foo(123).b == 123);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "orelse coercion as function argument" {
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
|
const Loc = struct { start: i32 = -1 };
|
||||||
|
const Container = struct {
|
||||||
|
a: ?Loc = null,
|
||||||
|
fn init(a: Loc) @This() {
|
||||||
|
return .{
|
||||||
|
.a = a,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var optional: ?Loc = .{};
|
||||||
|
var foo = Container.init(optional orelse .{});
|
||||||
|
try expect(foo.a.?.start == -1);
|
||||||
|
}
|
||||||
|
|||||||
@ -292,3 +292,12 @@ test "@sizeOf optional of previously unresolved union" {
|
|||||||
const Node = union { a: usize };
|
const Node = union { a: usize };
|
||||||
try expect(@sizeOf(?Node) == @sizeOf(Node) + @alignOf(Node));
|
try expect(@sizeOf(?Node) == @sizeOf(Node) + @alignOf(Node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "@offsetOf zero-bit field" {
|
||||||
|
const S = packed struct {
|
||||||
|
a: u32,
|
||||||
|
b: u0,
|
||||||
|
c: u32,
|
||||||
|
};
|
||||||
|
try expect(@offsetOf(S, "b") == @offsetOf(S, "c"));
|
||||||
|
}
|
||||||
|
|||||||
@ -20,4 +20,4 @@ export fn entry() void {
|
|||||||
//
|
//
|
||||||
// :11:27: error: expected type 'u8', found '?u8'
|
// :11:27: error: expected type 'u8', found '?u8'
|
||||||
// :11:27: note: cannot convert optional to payload type
|
// :11:27: note: cannot convert optional to payload type
|
||||||
// :11:27: note: consider using `.?`, `orelse`, or `if`
|
// :11:27: note: consider using '.?', 'orelse', or 'if'
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const MyStruct = struct {
|
||||||
|
a: i32,
|
||||||
|
b: i32,
|
||||||
|
|
||||||
|
pub fn getA(self: *List) i32 {
|
||||||
|
return self.items(.c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const List = std.MultiArrayList(MyStruct);
|
||||||
|
pub export fn entry() void {
|
||||||
|
var list = List{};
|
||||||
|
_ = MyStruct.getA(&list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
// backend=stage2
|
||||||
|
// target=native
|
||||||
|
//
|
||||||
|
// :7:28: error: no field named 'c' in enum 'meta.FieldEnum(tmp.MyStruct)'
|
||||||
|
// :?:?: note: enum declared here
|
||||||
@ -10,4 +10,4 @@ fn foo() !void {
|
|||||||
// target=native
|
// target=native
|
||||||
//
|
//
|
||||||
// :2:12: error: error is discarded
|
// :2:12: error: error is discarded
|
||||||
// :2:12: note: consider using `try`, `catch`, or `if`
|
// :2:12: note: consider using 'try', 'catch', or 'if'
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export fn quux() u32 {
|
|||||||
// :11:15: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.bar)).Fn.return_type.?).ErrorUnion.error_set!u32'
|
// :11:15: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.bar)).Fn.return_type.?).ErrorUnion.error_set!u32'
|
||||||
// :10:17: note: function cannot return an error
|
// :10:17: note: function cannot return an error
|
||||||
// :11:15: note: cannot convert error union to payload type
|
// :11:15: note: cannot convert error union to payload type
|
||||||
// :11:15: note: consider using `try`, `catch`, or `if`
|
// :11:15: note: consider using 'try', 'catch', or 'if'
|
||||||
// :15:14: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.bar)).Fn.return_type.?).ErrorUnion.error_set!u32'
|
// :15:14: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.bar)).Fn.return_type.?).ErrorUnion.error_set!u32'
|
||||||
// :15:14: note: cannot convert error union to payload type
|
// :15:14: note: cannot convert error union to payload type
|
||||||
// :15:14: note: consider using `try`, `catch`, or `if`
|
// :15:14: note: consider using 'try', 'catch', or 'if'
|
||||||
|
|||||||
@ -8,4 +8,4 @@ fn bar() anyerror!i32 { return 0; }
|
|||||||
// target=native
|
// target=native
|
||||||
//
|
//
|
||||||
// :2:14: error: error is ignored
|
// :2:14: error: error is ignored
|
||||||
// :2:14: note: consider using `try`, `catch`, or `if`
|
// :2:14: note: consider using 'try', 'catch', or 'if'
|
||||||
|
|||||||
@ -18,8 +18,8 @@ fn bad() anyerror!void {
|
|||||||
// target=native
|
// target=native
|
||||||
//
|
//
|
||||||
// :2:24: error: error is ignored
|
// :2:24: error: error is ignored
|
||||||
// :2:24: note: consider using `try`, `catch`, or `if`
|
// :2:24: note: consider using 'try', 'catch', or 'if'
|
||||||
// :6:25: error: error is ignored
|
// :6:25: error: error is ignored
|
||||||
// :6:25: note: consider using `try`, `catch`, or `if`
|
// :6:25: note: consider using 'try', 'catch', or 'if'
|
||||||
// :10:25: error: error is ignored
|
// :10:25: error: error is ignored
|
||||||
// :10:25: note: consider using `try`, `catch`, or `if`
|
// :10:25: note: consider using 'try', 'catch', or 'if'
|
||||||
|
|||||||
@ -11,3 +11,4 @@ export fn entry() u32 {
|
|||||||
// :3:17: error: cast increases pointer alignment
|
// :3:17: error: cast increases pointer alignment
|
||||||
// :3:32: note: '*u8' has alignment '1'
|
// :3:32: note: '*u8' has alignment '1'
|
||||||
// :3:26: note: '*u32' has alignment '4'
|
// :3:26: note: '*u32' has alignment '4'
|
||||||
|
// :3:17: note: consider using '@alignCast'
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
inline fn needComptime(comptime a: u64) void {
|
||||||
|
if (a != 0) @compileError("foo");
|
||||||
|
}
|
||||||
|
fn acceptRuntime(value: u64) void {
|
||||||
|
needComptime(value);
|
||||||
|
}
|
||||||
|
pub export fn entry() void {
|
||||||
|
var value: u64 = 0;
|
||||||
|
acceptRuntime(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
// backend=stage2
|
||||||
|
// target=native
|
||||||
|
//
|
||||||
|
// :5:18: error: unable to resolve comptime value
|
||||||
|
// :5:18: note: parameter is comptime
|
||||||
13
test/cases/compile_errors/invalid_decltest.zig
Normal file
13
test/cases/compile_errors/invalid_decltest.zig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export fn foo() void {
|
||||||
|
const a = 1;
|
||||||
|
struct {
|
||||||
|
test a {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
// backend=stage2
|
||||||
|
// target=native
|
||||||
|
//
|
||||||
|
// :4:14: error: cannot test a local constant
|
||||||
|
// :2:11: note: local constant declared here
|
||||||
12
test/cases/compile_errors/invalid_qualcast.zig
Normal file
12
test/cases/compile_errors/invalid_qualcast.zig
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
pub export fn entry() void {
|
||||||
|
var a: [*:0]const volatile u16 = undefined;
|
||||||
|
_ = @qualCast([*]u16, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
// backend=stage2
|
||||||
|
// target=native
|
||||||
|
//
|
||||||
|
// :3:9: error: '@qualCast' can only modify 'const' and 'volatile' qualifiers
|
||||||
|
// :3:9: note: expected type '[*]const volatile u16'
|
||||||
|
// :3:9: note: got type '[*:0]const volatile u16'
|
||||||
@ -10,5 +10,5 @@ export fn foo() void {
|
|||||||
//
|
//
|
||||||
// :4:9: error: expected type '*anyopaque', found '?*anyopaque'
|
// :4:9: error: expected type '*anyopaque', found '?*anyopaque'
|
||||||
// :4:9: note: cannot convert optional to payload type
|
// :4:9: note: cannot convert optional to payload type
|
||||||
// :4:9: note: consider using `.?`, `orelse`, or `if`
|
// :4:9: note: consider using '.?', 'orelse', or 'if'
|
||||||
// :4:9: note: '?*anyopaque' could have null values which are illegal in type '*anyopaque'
|
// :4:9: note: '?*anyopaque' could have null values which are illegal in type '*anyopaque'
|
||||||
|
|||||||
@ -9,3 +9,4 @@ export fn entry() void {
|
|||||||
// target=native
|
// target=native
|
||||||
//
|
//
|
||||||
// :3:15: error: cast discards const qualifier
|
// :3:15: error: cast discards const qualifier
|
||||||
|
// :3:15: note: consider using '@qualCast'
|
||||||
|
|||||||
@ -20,4 +20,4 @@ export fn entry() void {
|
|||||||
//
|
//
|
||||||
// :12:25: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'
|
// :12:25: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'
|
||||||
// :12:25: note: cannot convert error union to payload type
|
// :12:25: note: cannot convert error union to payload type
|
||||||
// :12:25: note: consider using `try`, `catch`, or `if`
|
// :12:25: note: consider using 'try', 'catch', or 'if'
|
||||||
|
|||||||
@ -17,4 +17,4 @@ pub const Container = struct {
|
|||||||
//
|
//
|
||||||
// :3:36: error: expected type 'i32', found '?i32'
|
// :3:36: error: expected type 'i32', found '?i32'
|
||||||
// :3:36: note: cannot convert optional to payload type
|
// :3:36: note: cannot convert optional to payload type
|
||||||
// :3:36: note: consider using `.?`, `orelse`, or `if`
|
// :3:36: note: consider using '.?', 'orelse', or 'if'
|
||||||
|
|||||||
@ -17,4 +17,4 @@ pub const Container = struct {
|
|||||||
//
|
//
|
||||||
// :3:36: error: expected type 'i32', found '?i32'
|
// :3:36: error: expected type 'i32', found '?i32'
|
||||||
// :3:36: note: cannot convert optional to payload type
|
// :3:36: note: cannot convert optional to payload type
|
||||||
// :3:36: note: consider using `.?`, `orelse`, or `if`
|
// :3:36: note: consider using '.?', 'orelse', or 'if'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user