aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorInKryption <inkryption07@gmail.com>2022-09-16 18:34:51 +0200
committerAndrew Kelley <andrew@ziglang.org>2022-10-27 22:00:47 -0400
commitbc72ae5e4e6d8f2253aed1316b053ad1022f9f67 (patch)
treeaa16a922bb65a479409d94c743880b6909b61112 /src
parent1d1c7ae5de3e981099522a8610764a6595b1b7a1 (diff)
downloadzig-bc72ae5e4e6d8f2253aed1316b053ad1022f9f67.tar.gz
zig-bc72ae5e4e6d8f2253aed1316b053ad1022f9f67.zip
Sema: Prevent coercion from tuple pointer to mutable slice.
Also fix some stdlib code affected by this. Co-authored by: topolarity <topolarity@tapscott.me>
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig55
1 files changed, 32 insertions, 23 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 931e06724b..608d6d986a 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -18208,7 +18208,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
return sema.analyzeDeclVal(block, src, new_decl_index);
},
.Fn => {
- const struct_val = union_val.val.castTag(.aggregate).?.data;
+ const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data;
// TODO use reflection instead of magic numbers here
// calling_convention: CallingConvention,
const cc = struct_val[0].toEnum(std.builtin.CallingConvention);
@@ -18242,12 +18242,17 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
break :alignment alignment;
}
};
+ const return_type = return_type_val.optionalValue() orelse
+ return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
+
var buf: Value.ToTypeBuffer = undefined;
const args_slice_val = args_val.castTag(.slice).?.data;
const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod.getTarget()));
- var param_types = try sema.arena.alloc(Type, args_len);
- var comptime_params = try sema.arena.alloc(bool, args_len);
+
+ const param_types = try sema.arena.alloc(Type, args_len);
+ const comptime_params = try sema.arena.alloc(bool, args_len);
+
var noalias_bits: u32 = 0;
var i: usize = 0;
while (i < args_len) : (i += 1) {
@@ -18275,11 +18280,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{});
param_types[i] = try param_type.toType(&buf).copy(sema.arena);
+ comptime_params[i] = false;
}
- const return_type = return_type_val.optionalValue() orelse
- return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
-
var fn_info = Type.Payload.Function.Data{
.param_types = param_types,
.comptime_params = comptime_params.ptr,
@@ -24075,20 +24078,23 @@ fn coerceExtra(
},
else => {},
},
- .Slice => {
- // pointer to tuple to slice
- if (inst_ty.isSinglePointer() and inst_ty.childType().isTuple() and dest_info.size == .Slice and
- sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
- {
- return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src);
+ .Slice => to_slice: {
+ if (inst_ty.zigTypeTag() == .Array) {
+ return sema.fail(
+ block,
+ inst_src,
+ "array literal requires address-of operator (&) to coerce to slice type '{}'",
+ .{dest_ty.fmt(sema.mod)},
+ );
}
+ if (!inst_ty.isSinglePointer()) break :to_slice;
+ const inst_child_ty = inst_ty.childType();
+ if (!inst_child_ty.isTuple()) break :to_slice;
+
// empty tuple to zero-length slice
// note that this allows coercing to a mutable slice.
- if (inst_ty.isSinglePointer() and
- inst_ty.childType().tag() == .empty_struct_literal and
- dest_info.size == .Slice)
- {
+ if (inst_child_ty.tupleFields().types.len == 0) {
const slice_val = try Value.Tag.slice.create(sema.arena, .{
.ptr = Value.undef,
.len = Value.zero,
@@ -24096,14 +24102,17 @@ fn coerceExtra(
return sema.addConstant(dest_ty, slice_val);
}
- if (inst_ty.zigTypeTag() == .Array) {
- return sema.fail(
- block,
- inst_src,
- "array literal requires address-of operator (&) to coerce to slice type '{}'",
- .{dest_ty.fmt(sema.mod)},
- );
+ // pointer to tuple to slice
+ if (dest_info.mutable) {
+ const err_msg = err_msg: {
+ const err_msg = try sema.errMsg(block, inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(sema.mod)});
+ errdefer err_msg.deinit(sema.gpa);
+ try sema.errNote(block, dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});
+ break :err_msg err_msg;
+ };
+ return sema.failWithOwnedErrorMsg(err_msg);
}
+ return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src);
},
.Many => p: {
if (!inst_ty.isSlice()) break :p;