aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-02-01 23:31:52 -0500
committerGitHub <noreply@github.com>2023-02-01 23:31:52 -0500
commit6b7ad22981867cbf6ec40d540f5571f276d6801b (patch)
tree4c1665cf0c03fcaa5d6c2a09aa49c49f5b804236 /src
parente712d5f03e6e3ddde6a4a6f7d2d82e786efd543a (diff)
parent629c3108aa71f94bd26dba8d4f20c9f3a3945bd4 (diff)
downloadzig-6b7ad22981867cbf6ec40d540f5571f276d6801b.tar.gz
zig-6b7ad22981867cbf6ec40d540f5571f276d6801b.zip
Merge pull request #14477 from Vexu/fixes
Improve `@ptrCast` errors, fix some bugs
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig39
-rw-r--r--src/BuiltinFn.zig8
-rw-r--r--src/Sema.zig101
-rw-r--r--src/TypedValue.zig5
-rw-r--r--src/Zir.zig6
-rw-r--r--src/print_zir.zig1
6 files changed, 148 insertions, 12 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 15b3611a1e..10673a2b37 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -2530,6 +2530,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
.bit_size_of,
.typeof_log2_int_type,
.ptr_to_int,
+ .qual_cast,
.align_of,
.bool_to_int,
.embed_file,
@@ -4278,7 +4279,34 @@ fn testDecl(
var num_namespaces_out: u32 = 0;
var capturing_namespace: ?*Scope.Namespace = null;
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,
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
.namespace, .enum_namespace => {
@@ -8010,6 +8038,7 @@ fn builtinCall(
.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),
.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),
// zig fmt: on
@@ -8692,6 +8721,7 @@ fn callExpr(
defer arg_block.unstack();
// `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);
_ = 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,
// and then rvalue() on that to pass the value to the result location.
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.break_result_info = parent_ri;
},
diff --git a/src/BuiltinFn.zig b/src/BuiltinFn.zig
index b71d96c3dd..80eb739185 100644
--- a/src/BuiltinFn.zig
+++ b/src/BuiltinFn.zig
@@ -75,6 +75,7 @@ pub const Tag = enum {
prefetch,
ptr_cast,
ptr_to_int,
+ qual_cast,
rem,
return_address,
select,
@@ -675,6 +676,13 @@ pub const list = list: {
},
},
.{
+ "@qualCast",
+ .{
+ .tag = .qual_cast,
+ .param_count = 2,
+ },
+ },
+ .{
"@rem",
.{
.tag = .rem,
diff --git a/src/Sema.zig b/src/Sema.zig
index 610f1bf5af..b7b3a55063 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1015,6 +1015,7 @@ fn analyzeBodyInner(
.float_cast => try sema.zirFloatCast(block, inst),
.int_cast => try sema.zirIntCast(block, inst),
.ptr_cast => try sema.zirPtrCast(block, inst),
+ .qual_cast => try sema.zirQualCast(block, inst),
.truncate => try sema.zirTruncate(block, inst),
.align_cast => try sema.zirAlignCast(block, inst),
.has_decl => try sema.zirHasDecl(block, inst),
@@ -3294,7 +3295,7 @@ fn ensureResultUsed(
const msg = msg: {
const msg = try sema.errMsg(block, src, "error is ignored", .{});
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;
};
return sema.failWithOwnedErrorMsg(msg);
@@ -3325,7 +3326,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
const msg = msg: {
const msg = try sema.errMsg(block, src, "error is discarded", .{});
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;
};
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);
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 = .{
.func_inst = func_inst,
@@ -6947,6 +6950,9 @@ fn analyzeInlineCallArg(
.val = arg_val,
};
} 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);
}
@@ -8467,7 +8473,7 @@ fn handleExternLibName(
return sema.fail(
block,
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 },
);
}
@@ -9004,7 +9010,18 @@ fn zirParam(
if (is_comptime and sema.preallocated_new_func != null) {
// We have a comptime value for this parameter so it should be elided from the
// 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);
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 dest_info = dest_ty.ptrInfo().data;
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") {
- 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") {
- 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();
@@ -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}'", .{
dest_ty.fmt(sema.mod), dest_align,
});
+
+ try sema.errNote(block, src, msg, "consider using '@alignCast'", .{});
break :msg 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);
}
+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 {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
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.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
@@ -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.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);
diff --git a/src/TypedValue.zig b/src/TypedValue.zig
index 6e096ee90a..cb28274f10 100644
--- a/src/TypedValue.zig
+++ b/src/TypedValue.zig
@@ -176,7 +176,9 @@ pub fn print(
var i: u32 = 0;
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 "";
@@ -390,6 +392,7 @@ pub fn print(
while (i < max_len) : (i += 1) {
var elem_buf: Value.ElemValueBuffer = undefined;
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;
}
diff --git a/src/Zir.zig b/src/Zir.zig
index 94e6a9a11a..b93422177e 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -857,6 +857,9 @@ pub const Inst = struct {
/// Implements the `@ptrCast` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
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.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
truncate,
@@ -1195,6 +1198,7 @@ pub const Inst = struct {
.float_cast,
.int_cast,
.ptr_cast,
+ .qual_cast,
.truncate,
.align_cast,
.has_field,
@@ -1484,6 +1488,7 @@ pub const Inst = struct {
.float_cast,
.int_cast,
.ptr_cast,
+ .qual_cast,
.truncate,
.align_cast,
.has_field,
@@ -1755,6 +1760,7 @@ pub const Inst = struct {
.float_cast = .pl_node,
.int_cast = .pl_node,
.ptr_cast = .pl_node,
+ .qual_cast = .pl_node,
.truncate = .pl_node,
.align_cast = .pl_node,
.typeof_builtin = .pl_node,
diff --git a/src/print_zir.zig b/src/print_zir.zig
index 6e8923bed9..e5fc8815ed 100644
--- a/src/print_zir.zig
+++ b/src/print_zir.zig
@@ -332,6 +332,7 @@ const Writer = struct {
.float_cast,
.int_cast,
.ptr_cast,
+ .qual_cast,
.truncate,
.align_cast,
.div_exact,