mirror of
https://github.com/ziglang/zig.git
synced 2025-12-20 13:13:16 +00:00
* AstGen: restore the param_type ZIR instruction and pass it to the
expression for function call arguments. This does not solve the
problem for generic function parameters, but it catches stage2 up to
stage1 which also does not solve the problem for generic function
parameters.
- Most of the enhancements in this commit will still be needed for a
more sophisticated further improvement to handle generic function
types.
- In Sema, handling of `as` coercion recognizes the `var_args_param`
Type Tag and passes the operand through doing no coercion.
- That was the last ZIR tag and we are now using all 256 ZIR tags.
* AstGen: array init and struct init expressions use the anon form even
when the result location has a type. Prevents the type system
incorrectly believing, for example, that a tuple is actually an array
when the result location is a param_type of a function with `anytype`
parameter.
* Sema: add missing coercion in `unionInit` to coerce the init to the
corresponding union field type.
* `Value.fieldValue` now takes a type and does not take an allocator.
closes #11293
After this commit, stage2 passes all the parser tests.
121 lines
4.1 KiB
Zig
121 lines
4.1 KiB
Zig
const builtin = @import("builtin");
|
|
const std = @import("std");
|
|
const expect = std.testing.expect;
|
|
const expectEqual = std.testing.expectEqual;
|
|
|
|
test "super basic invocations" {
|
|
const foo = struct {
|
|
fn foo() i32 {
|
|
return 1234;
|
|
}
|
|
}.foo;
|
|
try expect(@call(.{}, foo, .{}) == 1234);
|
|
comptime try expect(@call(.{ .modifier = .always_inline }, foo, .{}) == 1234);
|
|
{
|
|
// comptime call without comptime keyword
|
|
const result = @call(.{ .modifier = .compile_time }, foo, .{}) == 1234;
|
|
comptime try expect(result);
|
|
}
|
|
}
|
|
|
|
test "basic invocations" {
|
|
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
|
|
|
const foo = struct {
|
|
fn foo() i32 {
|
|
return 1234;
|
|
}
|
|
}.foo;
|
|
try expect(@call(.{}, foo, .{}) == 1234);
|
|
comptime {
|
|
// modifiers that allow comptime calls
|
|
try expect(@call(.{}, foo, .{}) == 1234);
|
|
try expect(@call(.{ .modifier = .no_async }, foo, .{}) == 1234);
|
|
try expect(@call(.{ .modifier = .always_tail }, foo, .{}) == 1234);
|
|
try expect(@call(.{ .modifier = .always_inline }, foo, .{}) == 1234);
|
|
}
|
|
{
|
|
// comptime call without comptime keyword
|
|
const result = @call(.{ .modifier = .compile_time }, foo, .{}) == 1234;
|
|
comptime try expect(result);
|
|
}
|
|
{
|
|
// call of non comptime-known function
|
|
var alias_foo = foo;
|
|
try expect(@call(.{ .modifier = .no_async }, alias_foo, .{}) == 1234);
|
|
try expect(@call(.{ .modifier = .never_tail }, alias_foo, .{}) == 1234);
|
|
try expect(@call(.{ .modifier = .never_inline }, alias_foo, .{}) == 1234);
|
|
}
|
|
}
|
|
|
|
test "tuple parameters" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
|
|
const add = struct {
|
|
fn add(a: i32, b: i32) i32 {
|
|
return a + b;
|
|
}
|
|
}.add;
|
|
var a: i32 = 12;
|
|
var b: i32 = 34;
|
|
try expect(@call(.{}, add, .{ a, 34 }) == 46);
|
|
try expect(@call(.{}, add, .{ 12, b }) == 46);
|
|
try expect(@call(.{}, add, .{ a, b }) == 46);
|
|
try expect(@call(.{}, add, .{ 12, 34 }) == 46);
|
|
if (builtin.zig_backend == .stage1) comptime try expect(@call(.{}, add, .{ 12, 34 }) == 46); // TODO
|
|
try expect(comptime @call(.{}, add, .{ 12, 34 }) == 46);
|
|
{
|
|
const separate_args0 = .{ a, b };
|
|
const separate_args1 = .{ a, 34 };
|
|
const separate_args2 = .{ 12, 34 };
|
|
const separate_args3 = .{ 12, b };
|
|
try expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46);
|
|
try expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46);
|
|
try expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46);
|
|
try expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46);
|
|
}
|
|
}
|
|
|
|
test "comptime call with bound function as parameter" {
|
|
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn ReturnType(func: anytype) type {
|
|
return switch (@typeInfo(@TypeOf(func))) {
|
|
.BoundFn => |info| info,
|
|
else => unreachable,
|
|
}.return_type orelse void;
|
|
}
|
|
|
|
fn call_me_maybe() ?i32 {
|
|
return 123;
|
|
}
|
|
};
|
|
|
|
var inst: S = undefined;
|
|
try expectEqual(?i32, S.ReturnType(inst.call_me_maybe));
|
|
}
|
|
|
|
test "result location of function call argument through runtime condition and struct init" {
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
const E = enum { a, b };
|
|
const S = struct {
|
|
e: E,
|
|
};
|
|
const namespace = struct {
|
|
fn foo(s: S) !void {
|
|
try expect(s.e == .b);
|
|
}
|
|
};
|
|
var runtime = true;
|
|
try namespace.foo(.{
|
|
.e = if (!runtime) .a else .b,
|
|
});
|
|
}
|