From 23b7d28896609e3f01765730599119baf53a56c9 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sun, 22 Jan 2023 16:40:00 +0100 Subject: std: restrict mem.span() and mem.len() to sentinel terminated pointers These functions are currently footgunny when working with pointers to arrays and slices. They just return the stated length of the array/slice without iterating and looking for the first sentinel, even if the array/slice is a sentinel terminated type. From looking at the quite small list of places in the standard library/compiler that this change breaks existing code, the new code looks to be more readable in all cases. The usage of std.mem.span/len was totally unneeded in most of the cases affected by this breaking change. We could remove these functions entirely in favor of other existing functions in std.mem such as std.mem.sliceTo(), but that would be a somewhat nasty breaking change as std.mem.span() is very widely used for converting sentinel terminated pointers to slices. It is however not at all widely used for anything else. Therefore I think it is better to break these few non-standard and potentially incorrect usages of these functions now and at some later time, if deemed worthwhile, finally remove these functions. If we wait for at least a full release cycle so that everyone adapts to this change first, updating for the removal could be a simple find and replace without needing to worry about the semantics. --- test/behavior/basic.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/behavior/basic.zig') diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index ebca81be96..8a97b3cbcd 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -703,7 +703,7 @@ test "string concatenation" { comptime try expect(@TypeOf(a) == *const [12:0]u8); comptime try expect(@TypeOf(b) == *const [12:0]u8); - const len = mem.len(b); + const len = b.len; const len_with_null = len + 1; { var i: u32 = 0; -- cgit v1.2.3 From 629c3108aa71f94bd26dba8d4f20c9f3a3945bd4 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 1 Feb 2023 21:41:02 +0200 Subject: AstGen: fix orelse type coercion in call arguments Closes #14506 --- src/AstGen.zig | 8 +++++++- test/behavior/basic.zig | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'test/behavior/basic.zig') diff --git a/src/AstGen.zig b/src/AstGen.zig index a5667ce9e8..10673a2b37 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -8721,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); @@ -10869,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/test/behavior/basic.zig b/test/behavior/basic.zig index 8a97b3cbcd..b82bfab99e 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -1125,3 +1125,21 @@ test "returning an opaque type from a function" { }; 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); +} -- cgit v1.2.3