Skip to content

Commit 7515187

Browse files
authoredJun 17, 2018
Merge pull request #1109 from ziglang/pass-by-non-copying-value
allow passing by non-copying value
·
0.15.20.3.0
2 parents 3ee4d23 + 472b7ef commit 7515187

File tree

16 files changed

+306
-344
lines changed

16 files changed

+306
-344
lines changed
 

‎doc/langref.html.in‎

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,39 +2818,30 @@ fn foo() void { }
28182818
{#code_end#}
28192819
{#header_open|Pass-by-value Parameters#}
28202820
<p>
2821-
In Zig, structs, unions, and enums with payloads cannot be passed by value
2822-
to a function.
2821+
In Zig, structs, unions, and enums with payloads can be passed directly to a function:
28232822
</p>
2824-
{#code_begin|test_err|not copyable; cannot pass by value#}
2825-
const Foo = struct {
2823+
{#code_begin|test#}
2824+
const Point = struct {
28262825
x: i32,
2826+
y: i32,
28272827
};
28282828

2829-
fn bar(foo: Foo) void {}
2830-
2831-
test "pass aggregate type by value to function" {
2832-
bar(Foo {.x = 12,});
2829+
fn foo(point: Point) i32 {
2830+
return point.x + point.y;
28332831
}
2834-
{#code_end#}
2835-
<p>
2836-
Instead, one must use <code>*const</code>. Zig allows implicitly casting something
2837-
to a const pointer to it:
2838-
</p>
2839-
{#code_begin|test#}
2840-
const Foo = struct {
2841-
x: i32,
2842-
};
28432832

2844-
fn bar(foo: *const Foo) void {}
2833+
const assert = @import("std").debug.assert;
28452834

2846-
test "implicitly cast to const pointer" {
2847-
bar(Foo {.x = 12,});
2835+
test "pass aggregate type by non-copy value to function" {
2836+
assert(foo(Point{ .x = 1, .y = 2 }) == 3);
28482837
}
28492838
{#code_end#}
28502839
<p>
2851-
However,
2852-
the C ABI does allow passing structs and unions by value. So functions which
2853-
use the C calling convention may pass structs and unions by value.
2840+
In this case, the value may be passed by reference, or by value, whichever way
2841+
Zig decides will be faster.
2842+
</p>
2843+
<p>
2844+
For extern functions, Zig follows the C ABI for passing structs and unions by value.
28542845
</p>
28552846
{#header_close#}
28562847
{#header_open|Function Reflection#}

‎src/analyze.cpp‎

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,10 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
11351135
gen_param_info->src_index = i;
11361136
gen_param_info->gen_index = SIZE_MAX;
11371137

1138-
type_ensure_zero_bits_known(g, type_entry);
1138+
ensure_complete_type(g, type_entry);
1139+
if (type_is_invalid(type_entry))
1140+
return g->builtin_types.entry_invalid;
1141+
11391142
if (type_has_bits(type_entry)) {
11401143
TypeTableEntry *gen_type;
11411144
if (handle_is_ptr(type_entry)) {
@@ -1546,12 +1549,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
15461549
case TypeTableEntryIdUnion:
15471550
case TypeTableEntryIdFn:
15481551
case TypeTableEntryIdPromise:
1549-
ensure_complete_type(g, type_entry);
1550-
if (calling_convention_allows_zig_types(fn_type_id.cc) && !type_is_copyable(g, type_entry)) {
1551-
add_node_error(g, param_node->data.param_decl.type,
1552-
buf_sprintf("type '%s' is not copyable; cannot pass by value", buf_ptr(&type_entry->name)));
1553-
return g->builtin_types.entry_invalid;
1554-
}
15551552
break;
15561553
}
15571554
FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];

‎src/codegen.cpp‎

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -326,13 +326,6 @@ static void addLLVMArgAttr(LLVMValueRef arg_val, unsigned param_index, const cha
326326
return addLLVMAttr(arg_val, param_index + 1, attr_name);
327327
}
328328

329-
static void addLLVMCallsiteAttr(LLVMValueRef call_instr, unsigned param_index, const char *attr_name) {
330-
unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
331-
assert(kind_id != 0);
332-
LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), kind_id, 0);
333-
LLVMAddCallSiteAttribute(call_instr, param_index + 1, llvm_attr);
334-
}
335-
336329
static bool is_symbol_available(CodeGen *g, Buf *name) {
337330
return g->exported_symbol_names.maybe_get(name) == nullptr && g->external_prototypes.maybe_get(name) == nullptr;
338331
}
@@ -581,11 +574,6 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
581574
if (param_type->id == TypeTableEntryIdPointer) {
582575
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull");
583576
}
584-
// Note: byval is disabled on windows due to an LLVM bug:
585-
// https://github.com/ziglang/zig/issues/536
586-
if (is_byval && g->zig_target.os != OsWindows) {
587-
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval");
588-
}
589577
}
590578

591579
uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
@@ -3114,15 +3102,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
31143102
}
31153103

31163104

3117-
for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
3118-
FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
3119-
// Note: byval is disabled on windows due to an LLVM bug:
3120-
// https://github.com/ziglang/zig/issues/536
3121-
if (gen_info->is_byval && g->zig_target.os != OsWindows) {
3122-
addLLVMCallsiteAttr(result, (unsigned)gen_info->gen_index, "byval");
3123-
}
3124-
}
3125-
31263105
if (instruction->is_async) {
31273106
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
31283107
LLVMBuildStore(g->builder, result, payload_ptr);

‎src/ir.cpp‎

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10463,13 +10463,6 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
1046310463
zig_unreachable();
1046410464
}
1046510465

10466-
static IrInstruction *ir_implicit_byval_const_ref_cast(IrAnalyze *ira, IrInstruction *inst) {
10467-
if (type_is_copyable(ira->codegen, inst->value.type))
10468-
return inst;
10469-
TypeTableEntry *const_ref_type = get_pointer_to_type(ira->codegen, inst->value.type, true);
10470-
return ir_implicit_cast(ira, inst, const_ref_type);
10471-
}
10472-
1047310466
static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {
1047410467
TypeTableEntry *type_entry = ptr->value.type;
1047510468
if (type_is_invalid(type_entry)) {
@@ -12283,7 +12276,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
1228312276
IrInstruction *casted_arg;
1228412277
if (is_var_args) {
1228512278
arg_part_of_generic_id = true;
12286-
casted_arg = ir_implicit_byval_const_ref_cast(ira, arg);
12279+
casted_arg = arg;
1228712280
} else {
1228812281
if (param_decl_node->data.param_decl.var_token == nullptr) {
1228912282
AstNode *param_type_node = param_decl_node->data.param_decl.type;
@@ -12296,7 +12289,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
1229612289
return false;
1229712290
} else {
1229812291
arg_part_of_generic_id = true;
12299-
casted_arg = ir_implicit_byval_const_ref_cast(ira, arg);
12292+
casted_arg = arg;
1230012293
}
1230112294
}
1230212295

@@ -12515,9 +12508,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1251512508

1251612509
size_t next_proto_i = 0;
1251712510
if (first_arg_ptr) {
12518-
IrInstruction *first_arg;
1251912511
assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer);
12520-
if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
12512+
12513+
bool first_arg_known_bare = false;
12514+
if (fn_type_id->next_param_index >= 1) {
12515+
TypeTableEntry *param_type = fn_type_id->param_info[next_proto_i].type;
12516+
if (type_is_invalid(param_type))
12517+
return ira->codegen->builtin_types.entry_invalid;
12518+
first_arg_known_bare = param_type->id != TypeTableEntryIdPointer;
12519+
}
12520+
12521+
IrInstruction *first_arg;
12522+
if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
1252112523
first_arg = first_arg_ptr;
1252212524
} else {
1252312525
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
@@ -12667,9 +12669,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1266712669
size_t next_proto_i = 0;
1266812670

1266912671
if (first_arg_ptr) {
12670-
IrInstruction *first_arg;
1267112672
assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer);
12672-
if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
12673+
12674+
bool first_arg_known_bare = false;
12675+
if (fn_type_id->next_param_index >= 1) {
12676+
TypeTableEntry *param_type = fn_type_id->param_info[next_proto_i].type;
12677+
if (type_is_invalid(param_type))
12678+
return ira->codegen->builtin_types.entry_invalid;
12679+
first_arg_known_bare = param_type->id != TypeTableEntryIdPointer;
12680+
}
12681+
12682+
IrInstruction *first_arg;
12683+
if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
1267312684
first_arg = first_arg_ptr;
1267412685
} else {
1267512686
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
@@ -12802,10 +12813,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1280212813
return ira->codegen->builtin_types.entry_invalid;
1280312814
}
1280412815
if (inst_fn_type_id.async_allocator_type == nullptr) {
12805-
IrInstruction *casted_inst = ir_implicit_byval_const_ref_cast(ira, uncasted_async_allocator_inst);
12806-
if (type_is_invalid(casted_inst->value.type))
12807-
return ira->codegen->builtin_types.entry_invalid;
12808-
inst_fn_type_id.async_allocator_type = casted_inst->value.type;
12816+
inst_fn_type_id.async_allocator_type = uncasted_async_allocator_inst->value.type;
1280912817
}
1281012818
async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, inst_fn_type_id.async_allocator_type);
1281112819
if (type_is_invalid(async_allocator_inst->value.type))
@@ -12866,20 +12874,23 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1286612874
IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count);
1286712875
size_t next_arg_index = 0;
1286812876
if (first_arg_ptr) {
12869-
IrInstruction *first_arg;
1287012877
assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer);
12871-
if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
12878+
12879+
TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type;
12880+
if (type_is_invalid(param_type))
12881+
return ira->codegen->builtin_types.entry_invalid;
12882+
12883+
IrInstruction *first_arg;
12884+
if (param_type->id == TypeTableEntryIdPointer &&
12885+
handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type))
12886+
{
1287212887
first_arg = first_arg_ptr;
1287312888
} else {
1287412889
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
1287512890
if (type_is_invalid(first_arg->value.type))
1287612891
return ira->codegen->builtin_types.entry_invalid;
1287712892
}
1287812893

12879-
TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type;
12880-
if (type_is_invalid(param_type))
12881-
return ira->codegen->builtin_types.entry_invalid;
12882-
1288312894
IrInstruction *casted_arg = ir_implicit_cast(ira, first_arg, param_type);
1288412895
if (type_is_invalid(casted_arg->value.type))
1288512896
return ira->codegen->builtin_types.entry_invalid;

‎std/array_list.zig‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,36 +29,36 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
2929
};
3030
}
3131

32-
pub fn deinit(self: *const Self) void {
32+
pub fn deinit(self: Self) void {
3333
self.allocator.free(self.items);
3434
}
3535

36-
pub fn toSlice(self: *const Self) []align(A) T {
36+
pub fn toSlice(self: Self) []align(A) T {
3737
return self.items[0..self.len];
3838
}
3939

40-
pub fn toSliceConst(self: *const Self) []align(A) const T {
40+
pub fn toSliceConst(self: Self) []align(A) const T {
4141
return self.items[0..self.len];
4242
}
4343

44-
pub fn at(self: *const Self, n: usize) T {
44+
pub fn at(self: Self, n: usize) T {
4545
return self.toSliceConst()[n];
4646
}
4747

4848
/// Sets the value at index `i`, or returns `error.OutOfBounds` if
4949
/// the index is not in range.
50-
pub fn setOrError(self: *const Self, i: usize, item: *const T) !void {
50+
pub fn setOrError(self: Self, i: usize, item: T) !void {
5151
if (i >= self.len) return error.OutOfBounds;
52-
self.items[i] = item.*;
52+
self.items[i] = item;
5353
}
5454

5555
/// Sets the value at index `i`, asserting that the value is in range.
56-
pub fn set(self: *const Self, i: usize, item: *const T) void {
56+
pub fn set(self: *Self, i: usize, item: T) void {
5757
assert(i < self.len);
58-
self.items[i] = item.*;
58+
self.items[i] = item;
5959
}
6060

61-
pub fn count(self: *const Self) usize {
61+
pub fn count(self: Self) usize {
6262
return self.len;
6363
}
6464

@@ -81,12 +81,12 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
8181
return result;
8282
}
8383

84-
pub fn insert(self: *Self, n: usize, item: *const T) !void {
84+
pub fn insert(self: *Self, n: usize, item: T) !void {
8585
try self.ensureCapacity(self.len + 1);
8686
self.len += 1;
8787

8888
mem.copy(T, self.items[n + 1 .. self.len], self.items[n .. self.len - 1]);
89-
self.items[n] = item.*;
89+
self.items[n] = item;
9090
}
9191

9292
pub fn insertSlice(self: *Self, n: usize, items: []align(A) const T) !void {
@@ -97,9 +97,9 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
9797
mem.copy(T, self.items[n .. n + items.len], items);
9898
}
9999

100-
pub fn append(self: *Self, item: *const T) !void {
100+
pub fn append(self: *Self, item: T) !void {
101101
const new_item_ptr = try self.addOne();
102-
new_item_ptr.* = item.*;
102+
new_item_ptr.* = item;
103103
}
104104

105105
pub fn appendSlice(self: *Self, items: []align(A) const T) !void {

‎std/build.zig‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ pub const Builder = struct {
234234
defer wanted_steps.deinit();
235235

236236
if (step_names.len == 0) {
237-
try wanted_steps.append(&self.default_step);
237+
try wanted_steps.append(self.default_step);
238238
} else {
239239
for (step_names) |step_name| {
240240
const s = try self.getTopLevelStepByName(step_name);

‎std/fmt/index.zig‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,6 @@ pub fn formatType(
162162
},
163163
builtin.TypeInfo.Pointer.Size.Many => {
164164
if (ptr_info.child == u8) {
165-
//This is a bit of a hack, but it made more sense to
166-
// do this check here than have formatText do it
167165
if (fmt[0] == 's') {
168166
const len = std.cstr.len(value);
169167
return formatText(value[0..len], fmt, context, Errors, output);
@@ -176,6 +174,12 @@ pub fn formatType(
176174
return output(context, casted_value);
177175
},
178176
},
177+
builtin.TypeId.Array => |info| {
178+
if (info.child == u8) {
179+
return formatText(value, fmt, context, Errors, output);
180+
}
181+
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
182+
},
179183
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
180184
}
181185
}

‎std/json.zig‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,7 @@ pub const Parser = struct {
13261326
},
13271327
// Array Parent -> [ ..., <array>, value ]
13281328
Value.Array => |*array| {
1329-
try array.append(value);
1329+
try array.append(value.*);
13301330
p.state = State.ArrayValue;
13311331
},
13321332
else => {

‎std/math/big/int.zig‎

Lines changed: 144 additions & 202 deletions
Large diffs are not rendered by default.

‎std/mem.zig‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,12 @@ pub const Allocator = struct {
4040

4141
/// Call destroy with the result
4242
/// TODO once #733 is solved, this will replace create
43-
pub fn construct(self: *Allocator, init: var) t: {
44-
// TODO this is a workaround for type getting parsed as Error!&const T
45-
const T = @typeOf(init).Child;
46-
break :t Error!*T;
47-
} {
48-
const T = @typeOf(init).Child;
43+
pub fn construct(self: *Allocator, init: var) Error!*@typeOf(init) {
44+
const T = @typeOf(init);
4945
if (@sizeOf(T) == 0) return &{};
5046
const slice = try self.alloc(T, 1);
5147
const ptr = &slice[0];
52-
ptr.* = init.*;
48+
ptr.* = init;
5349
return ptr;
5450
}
5551

‎test/behavior.zig‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ comptime {
1313
_ = @import("cases/bugs/656.zig");
1414
_ = @import("cases/bugs/828.zig");
1515
_ = @import("cases/bugs/920.zig");
16+
_ = @import("cases/byval_arg_var.zig");
1617
_ = @import("cases/cast.zig");
1718
_ = @import("cases/const_slice_child.zig");
1819
_ = @import("cases/coroutines.zig");

‎test/cases/byval_arg_var.zig‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const std = @import("std");
2+
3+
var result: []const u8 = "wrong";
4+
5+
test "aoeu" {
6+
start();
7+
blowUpStack(10);
8+
9+
std.debug.assert(std.mem.eql(u8, result, "string literal"));
10+
}
11+
12+
fn start() void {
13+
foo("string literal");
14+
}
15+
16+
fn foo(x: var) void {
17+
bar(x);
18+
}
19+
20+
fn bar(x: var) void {
21+
result = x;
22+
}
23+
24+
fn blowUpStack(x: u32) void {
25+
if (x == 0) return;
26+
blowUpStack(x - 1);
27+
}

‎test/cases/cast.zig‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -318,14 +318,6 @@ fn testCastConstArrayRefToConstSlice() void {
318318
assert(mem.eql(u8, slice, "aoeu"));
319319
}
320320

321-
test "var args implicitly casts by value arg to const ref" {
322-
foo("hello");
323-
}
324-
325-
fn foo(args: ...) void {
326-
assert(@typeOf(args[0]) == *const [5]u8);
327-
}
328-
329321
test "peer type resolution: error and [N]T" {
330322
// TODO: implicit error!T to error!U where T can implicitly cast to U
331323
//assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));

‎test/cases/fn.zig‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,60 @@ test "assign inline fn to const variable" {
119119
}
120120

121121
inline fn inlineFn() void {}
122+
123+
test "pass by non-copying value" {
124+
assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
125+
}
126+
127+
const Point = struct {
128+
x: i32,
129+
y: i32,
130+
};
131+
132+
fn addPointCoords(pt: Point) i32 {
133+
return pt.x + pt.y;
134+
}
135+
136+
test "pass by non-copying value through var arg" {
137+
assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
138+
}
139+
140+
fn addPointCoordsVar(pt: var) i32 {
141+
comptime assert(@typeOf(pt) == Point);
142+
return pt.x + pt.y;
143+
}
144+
145+
test "pass by non-copying value as method" {
146+
var pt = Point2{ .x = 1, .y = 2 };
147+
assert(pt.addPointCoords() == 3);
148+
}
149+
150+
const Point2 = struct {
151+
x: i32,
152+
y: i32,
153+
154+
fn addPointCoords(self: Point2) i32 {
155+
return self.x + self.y;
156+
}
157+
};
158+
159+
test "pass by non-copying value as method, which is generic" {
160+
var pt = Point3{ .x = 1, .y = 2 };
161+
assert(pt.addPointCoords(i32) == 3);
162+
}
163+
164+
const Point3 = struct {
165+
x: i32,
166+
y: i32,
167+
168+
fn addPointCoords(self: Point3, comptime T: type) i32 {
169+
return self.x + self.y;
170+
}
171+
};
172+
173+
test "pass by non-copying value as method, at comptime" {
174+
comptime {
175+
var pt = Point2{ .x = 1, .y = 2 };
176+
assert(pt.addPointCoords() == 3);
177+
}
178+
}

‎test/cases/var_args.zig‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,6 @@ test "array of var args functions" {
7575
assert(!foos[1]());
7676
}
7777

78-
test "pass array and slice of same array to var args should have same pointers" {
79-
const array = "hi";
80-
const slice: []const u8 = array;
81-
return assertSlicePtrsEql(array, slice);
82-
}
83-
84-
fn assertSlicePtrsEql(args: ...) void {
85-
const s1 = ([]const u8)(args[0]);
86-
const s2 = args[1];
87-
assert(s1.ptr == s2.ptr);
88-
}
89-
9078
test "pass zero length array to var args param" {
9179
doNothingWithFirstArg("");
9280
}

‎test/compile_errors.zig‎

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2215,7 +2215,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
22152215
\\ derp.init();
22162216
\\}
22172217
,
2218-
".tmp_source.zig:14:5: error: expected type 'i32', found '*const Foo'",
2218+
".tmp_source.zig:14:5: error: expected type 'i32', found 'Foo'",
22192219
);
22202220

22212221
cases.add(
@@ -2573,15 +2573,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
25732573
break :x tc;
25742574
});
25752575

2576-
cases.add(
2577-
"pass non-copyable type by value to function",
2578-
\\const Point = struct { x: i32, y: i32, };
2579-
\\fn foo(p: Point) void { }
2580-
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
2581-
,
2582-
".tmp_source.zig:2:11: error: type 'Point' is not copyable; cannot pass by value",
2583-
);
2584-
25852576
cases.add(
25862577
"implicit cast from array to mutable slice",
25872578
\\var global_array: [10]i32 = undefined;
@@ -4066,20 +4057,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
40664057
".tmp_source.zig:3:5: note: field 'A' has type 'i32'",
40674058
);
40684059

4069-
cases.add(
4070-
"self-referencing function pointer field",
4071-
\\const S = struct {
4072-
\\ f: fn(_: S) void,
4073-
\\};
4074-
\\fn f(_: S) void {
4075-
\\}
4076-
\\export fn entry() void {
4077-
\\ var _ = S { .f = f };
4078-
\\}
4079-
,
4080-
".tmp_source.zig:4:9: error: type 'S' is not copyable; cannot pass by value",
4081-
);
4082-
40834060
cases.add(
40844061
"taking offset of void field in struct",
40854062
\\const Empty = struct {

0 commit comments

Comments
 (0)
Please sign in to comment.