diff options
| author | InKryption <inkryption07@gmail.com> | 2022-09-16 18:34:51 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-10-27 22:00:47 -0400 |
| commit | bc72ae5e4e6d8f2253aed1316b053ad1022f9f67 (patch) | |
| tree | aa16a922bb65a479409d94c743880b6909b61112 /src | |
| parent | 1d1c7ae5de3e981099522a8610764a6595b1b7a1 (diff) | |
| download | zig-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.zig | 55 |
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; |
