parent
a7d59086b4
commit
59b3dc8907
|
@ -2797,39 +2797,30 @@ fn foo() void { }
|
|||
{#code_end#}
|
||||
{#header_open|Pass-by-value Parameters#}
|
||||
<p>
|
||||
In Zig, structs, unions, and enums with payloads cannot be passed by value
|
||||
to a function.
|
||||
</p>
|
||||
{#code_begin|test_err|not copyable; cannot pass by value#}
|
||||
const Foo = struct {
|
||||
x: i32,
|
||||
};
|
||||
|
||||
fn bar(foo: Foo) void {}
|
||||
|
||||
test "pass aggregate type by value to function" {
|
||||
bar(Foo {.x = 12,});
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
Instead, one must use <code>*const</code>. Zig allows implicitly casting something
|
||||
to a const pointer to it:
|
||||
In Zig, structs, unions, and enums with payloads can be passed directly to a function:
|
||||
</p>
|
||||
{#code_begin|test#}
|
||||
const Foo = struct {
|
||||
const Point = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
|
||||
fn bar(foo: *const Foo) void {}
|
||||
fn foo(point: Point) i32 {
|
||||
return point.x + point.y;
|
||||
}
|
||||
|
||||
test "implicitly cast to const pointer" {
|
||||
bar(Foo {.x = 12,});
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "pass aggregate type by non-copy value to function" {
|
||||
assert(foo(Point{ .x = 1, .y = 2 }) == 3);
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
However,
|
||||
the C ABI does allow passing structs and unions by value. So functions which
|
||||
use the C calling convention may pass structs and unions by value.
|
||||
In this case, the value may be passed by reference, or by value, whichever way
|
||||
Zig decides will be faster.
|
||||
</p>
|
||||
<p>
|
||||
For extern functions, Zig follows the C ABI for passing structs and unions by value.
|
||||
</p>
|
||||
{#header_close#}
|
||||
{#header_open|Function Reflection#}
|
||||
|
|
|
@ -1135,7 +1135,10 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
|||
gen_param_info->src_index = i;
|
||||
gen_param_info->gen_index = SIZE_MAX;
|
||||
|
||||
type_ensure_zero_bits_known(g, type_entry);
|
||||
ensure_complete_type(g, type_entry);
|
||||
if (type_is_invalid(type_entry))
|
||||
return g->builtin_types.entry_invalid;
|
||||
|
||||
if (type_has_bits(type_entry)) {
|
||||
TypeTableEntry *gen_type;
|
||||
if (handle_is_ptr(type_entry)) {
|
||||
|
@ -1546,12 +1549,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
|||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdPromise:
|
||||
ensure_complete_type(g, type_entry);
|
||||
if (calling_convention_allows_zig_types(fn_type_id.cc) && !type_is_copyable(g, type_entry)) {
|
||||
add_node_error(g, param_node->data.param_decl.type,
|
||||
buf_sprintf("type '%s' is not copyable; cannot pass by value", buf_ptr(&type_entry->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
|
||||
|
|
|
@ -119,3 +119,16 @@ test "assign inline fn to const variable" {
|
|||
}
|
||||
|
||||
inline fn inlineFn() void {}
|
||||
|
||||
test "pass by non-copying value" {
|
||||
assert(bar(Point{ .x = 1, .y = 2 }) == 3);
|
||||
}
|
||||
|
||||
const Point = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
|
||||
fn bar(pt: Point) i32 {
|
||||
return pt.x + pt.y;
|
||||
}
|
||||
|
|
|
@ -2573,15 +2573,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
break :x tc;
|
||||
});
|
||||
|
||||
cases.add(
|
||||
"pass non-copyable type by value to function",
|
||||
\\const Point = struct { x: i32, y: i32, };
|
||||
\\fn foo(p: Point) void { }
|
||||
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
|
||||
,
|
||||
".tmp_source.zig:2:11: error: type 'Point' is not copyable; cannot pass by value",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"implicit cast from array to mutable slice",
|
||||
\\var global_array: [10]i32 = undefined;
|
||||
|
@ -4066,20 +4057,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
".tmp_source.zig:3:5: note: field 'A' has type 'i32'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"self-referencing function pointer field",
|
||||
\\const S = struct {
|
||||
\\ f: fn(_: S) void,
|
||||
\\};
|
||||
\\fn f(_: S) void {
|
||||
\\}
|
||||
\\export fn entry() void {
|
||||
\\ var _ = S { .f = f };
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:4:9: error: type 'S' is not copyable; cannot pass by value",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"taking offset of void field in struct",
|
||||
\\const Empty = struct {
|
||||
|
|
Loading…
Reference in New Issue
Block a user