╭ fn.zig ───────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
.. conflicting_externs/ hasdecl/ import/ namespace_depends_on_compile_var/ pub_enum/ x86_64/ zon/ abs.zig addrspace_and_linksection.zig align.zig alignof.zig array.zig asm.zig atomics.zig backing_int.zig basic.zig bit_shifting.zig bitcast.zig bitreverse.zig bool.zig builtin_functions_returning_void_ byteswap.zig byval_arg_var.zig call.zig cast.zig cast_int.zig comptime_memory.zig const_slice_child.zig decl_literals.zig decltest.zig defer.zig destructure.zig duplicated_test_names.zig enum.zig error.zig eval.zig export_builtin.zig export_c_keywords.zig export_keyword.zig export_self_referential_type_info extern.zig extern_struct_zero_size_fields.zi field_parent_ptr.zig file_to_embed.txt floatop.zig ╭─────────────────────────────────╮ │fn.zig │ ╰─────────────────────────────────╯ fn_delegation.zig fn_in_struct_in_comptime.zig for.zig generics.zig globals.zig hasdecl.zig hasfield.zig if.zig import.zig import_c_keywords.zig incomplete_struct_param_tld.zig inline_switch.zig int128.zig int_comparison_elision.zig ir_block_deps.zig lower_strlit_to_vector.zig math.zig maximum_minimum.zig member_func.zig memcpy.zig memmove.zig memset.zig merge_error_sets.zig muladd.zig multiple_externs_with_conflicting namespace_depends_on_compile_var. nan.zig null.zig optional.zig overlapping_assign.zig packed-struct.zig packed-union.zig packed_struct_explicit_backing_in pointers.zig popcount.zig prefetch.zig ptrcast.zig ptrfromint.zig pub_enum.zig ref_var_in_if_after_if_2nd_switch reflection.zig return_address.zig saturating_arithmetic.zig select.zig shuffle.zig sizeof_and_typeof.zig slice.zig slice_sentinel_comptime.zig spirv.zig splat.zig src.zig string_literals.zig struct.zig struct_contains_null_ptr_itself.z struct_contains_slice_of_itself.z switch.zig switch_loop.zig switch_on_captured_error.zig switch_prong_err_enum.zig switch_prong_implicit_cast.zig this.zig threadlocal.zig truncate.zig try.zig tuple.zig tuple_declarations.zig type.zig type_info.zig typename.zig undefined.zig underscore.zig union.zig var_args.zig vector.zig void.zig wasm.zig while.zig widening.zig wrapping_arithmetic.zig x86_64.zig zero.bin zon.zig
1 const std = @import("std"); 2 const builtin = @import("builtin"); 3 const testing = std.testing; 4 const assert = std.debug.assert; 5 const expect = testing.expect; 6 const expectEqual = testing.expectEqual; 7 8 test "params" { 9 try expect(testParamsAdd(22, 11) == 33); 10 } 11 fn testParamsAdd(a: i32, b: i32) i32 { 12 return a + b; 13 } 14 15 test "local variables" { 16 testLocVars(2); 17 } 18 fn testLocVars(b: i32) void { 19 const a: i32 = 1; 20 if (a + b != 3) unreachable; 21 } 22 23 test "mutable local variables" { 24 var zero: i32 = 0; 25 _ = &zero; 26 try expect(zero == 0); 27 28 var i = @as(i32, 0); 29 while (i != 3) { 30 i += 1; 31 } 32 try expect(i == 3); 33 } 34 35 test "separate block scopes" { 36 { 37 const no_conflict: i32 = 5; 38 try expect(no_conflict == 5); 39 } 40 41 const c = x: { 42 const no_conflict = @as(i32, 10); 43 break :x no_conflict; 44 }; 45 try expect(c == 10); 46 } 47 48 fn @"weird function name"() i32 { 49 return 1234; 50 } 51 test "weird function name" { 52 try expect(@"weird function name"() == 1234); 53 } 54 55 test "assign inline fn to const variable" { 56 const a = inlineFn; 57 a(); 58 } 59 60 inline fn inlineFn() void {} 61 62 fn outer(y: u32) *const fn (u32) u32 { 63 const Y = @TypeOf(y); 64 const st = struct { 65 fn get(z: u32) u32 { 66 return z + @sizeOf(Y); 67 } 68 }; 69 return st.get; 70 } 71 72 test "return inner function which references comptime variable of outer function" { 73 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 74 75 const func = outer(10); 76 try expect(func(3) == 7); 77 } 78 79 test "discard the result of a function that returns a struct" { 80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 81 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 82 83 const S = struct { 84 fn entry() void { 85 _ = func(); 86 } 87 88 fn func() Foo { 89 return undefined; 90 } 91 92 const Foo = struct { 93 a: u64, 94 b: u64, 95 }; 96 }; 97 S.entry(); 98 comptime S.entry(); 99 } 100 101 test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" { 102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 104 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 105 106 const S = struct { 107 field: u32, 108 109 fn doTheTest() !void { 110 bar2 = actualFn; 111 const result = try foo(); 112 try expect(result.field == 1234); 113 } 114 115 const Foo = struct { field: u32 }; 116 117 fn foo() !Foo { 118 var res: Foo = undefined; 119 res.field = bar(); 120 return res; 121 } 122 123 inline fn bar() u32 { 124 return bar2.?(); 125 } 126 127 var bar2: ?*const fn () u32 = null; 128 129 fn actualFn() u32 { 130 return 1234; 131 } 132 }; 133 try S.doTheTest(); 134 } 135 136 test "implicit cast function unreachable return" { 137 wantsFnWithVoid(fnWithUnreachable); 138 } 139 140 fn wantsFnWithVoid(comptime f: fn () void) void { 141 _ = f; 142 } 143 144 fn fnWithUnreachable() noreturn { 145 unreachable; 146 } 147 148 test "extern struct with stdcallcc fn pointer" { 149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 150 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 151 152 const S = extern struct { 153 ptr: *const fn () callconv(if (builtin.target.cpu.arch == .x86) .{ .x86_stdcall = .{} } else .c) i32, 154 155 fn foo() callconv(if (builtin.target.cpu.arch == .x86) .{ .x86_stdcall = .{} } else .c) i32 { 156 return 1234; 157 } 158 }; 159 160 var s: S = undefined; 161 s.ptr = S.foo; 162 try expect(s.ptr() == 1234); 163 } 164 165 const nComplexCallconv = 100; 166 fn fComplexCallconvRet(x: u32) callconv(blk: { 167 const s: struct { n: u32 } = .{ .n = nComplexCallconv }; 168 break :blk switch (s.n) { 169 0 => .c, 170 1 => .@"inline", 171 else => .auto, 172 }; 173 }) struct { x: u32 } { 174 return .{ .x = x * x }; 175 } 176 177 test "function with complex callconv and return type expressions" { 178 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 179 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 180 181 try expect(fComplexCallconvRet(3).x == 9); 182 } 183 184 test "pass by non-copying value" { 185 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 186 187 try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3); 188 } 189 190 const Point = struct { 191 x: i32, 192 y: i32, 193 }; 194 195 fn addPointCoords(pt: Point) i32 { 196 return pt.x + pt.y; 197 } 198 199 test "pass by non-copying value through var arg" { 200 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 201 202 try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3); 203 } 204 205 fn addPointCoordsVar(pt: anytype) !i32 { 206 comptime assert(@TypeOf(pt) == Point); 207 return pt.x + pt.y; 208 } 209 210 test "pass by non-copying value as method" { 211 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 212 213 var pt = Point2{ .x = 1, .y = 2 }; 214 try expect(pt.addPointCoords() == 3); 215 } 216 217 const Point2 = struct { 218 x: i32, 219 y: i32, 220 221 fn addPointCoords(self: Point2) i32 { 222 return self.x + self.y; 223 } 224 }; 225 226 test "pass by non-copying value as method, which is generic" { 227 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 228 229 var pt = Point3{ .x = 1, .y = 2 }; 230 try expect(pt.addPointCoords(i32) == 3); 231 } 232 233 const Point3 = struct { 234 x: i32, 235 y: i32, 236 237 fn addPointCoords(self: Point3, comptime T: type) i32 { 238 _ = T; 239 return self.x + self.y; 240 } 241 }; 242 243 test "pass by non-copying value as method, at comptime" { 244 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 245 246 comptime { 247 var pt = Point2{ .x = 1, .y = 2 }; 248 try expect(pt.addPointCoords() == 3); 249 } 250 } 251 252 test "implicit cast fn call result to optional in field result" { 253 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 254 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 255 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 256 257 const S = struct { 258 fn entry() !void { 259 const x = Foo{ 260 .field = optionalPtr(), 261 }; 262 try expect(x.field.?.* == 999); 263 } 264 265 const glob: i32 = 999; 266 267 fn optionalPtr() *const i32 { 268 return &glob; 269 } 270 271 const Foo = struct { 272 field: ?*const i32, 273 }; 274 }; 275 try S.entry(); 276 try comptime S.entry(); 277 } 278 279 test "void parameters" { 280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 281 282 try voidFun(1, {}, 2, {}); 283 } 284 fn voidFun(a: i32, b: void, c: i32, d: void) !void { 285 _ = d; 286 const v = b; 287 const vv: void = if (a == 1) v else {}; 288 try expect(a + c == 3); 289 return vv; 290 } 291 292 test "call function with empty string" { 293 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 294 295 acceptsString(""); 296 } 297 298 fn acceptsString(foo: []u8) void { 299 _ = foo; 300 } 301 302 test "function pointers" { 303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 305 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 306 307 const fns = [_]*const @TypeOf(fn1){ 308 &fn1, 309 &fn2, 310 &fn3, 311 &fn4, 312 }; 313 for (fns, 0..) |f, i| { 314 try expect(f() == @as(u32, @intCast(i)) + 5); 315 } 316 } 317 fn fn1() u32 { 318 return 5; 319 } 320 fn fn2() u32 { 321 return 6; 322 } 323 fn fn3() u32 { 324 return 7; 325 } 326 fn fn4() u32 { 327 return 8; 328 } 329 330 test "number literal as an argument" { 331 try numberLiteralArg(3); 332 try comptime numberLiteralArg(3); 333 } 334 335 fn numberLiteralArg(a: anytype) !void { 336 try expect(a == 3); 337 } 338 339 test "function call with anon list literal" { 340 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 341 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 342 343 const S = struct { 344 fn doTheTest() !void { 345 try consumeVec(.{ 9, 8, 7 }); 346 } 347 348 fn consumeVec(vec: [3]f32) !void { 349 try expect(vec[0] == 9); 350 try expect(vec[1] == 8); 351 try expect(vec[2] == 7); 352 } 353 }; 354 try S.doTheTest(); 355 try comptime S.doTheTest(); 356 } 357 358 test "function call with anon list literal - 2D" { 359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 360 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 361 362 const S = struct { 363 fn doTheTest() !void { 364 try consumeVec(.{ .{ 9, 8 }, .{ 7, 6 } }); 365 } 366 367 fn consumeVec(vec: [2][2]f32) !void { 368 try expect(vec[0][0] == 9); 369 try expect(vec[0][1] == 8); 370 try expect(vec[1][0] == 7); 371 try expect(vec[1][1] == 6); 372 } 373 }; 374 try S.doTheTest(); 375 try comptime S.doTheTest(); 376 } 377 378 test "ability to give comptime types and non comptime types to same parameter" { 379 const S = struct { 380 fn doTheTest() !void { 381 var x: i32 = 1; 382 _ = &x; 383 try expect(foo(x) == 10); 384 try expect(foo(i32) == 20); 385 } 386 387 fn foo(arg: anytype) i32 { 388 if (@typeInfo(@TypeOf(arg)) == .type and arg == i32) return 20; 389 return 9 + arg; 390 } 391 }; 392 try S.doTheTest(); 393 try comptime S.doTheTest(); 394 } 395 396 test "function with inferred error set but returning no error" { 397 const S = struct { 398 fn foo() !void {} 399 }; 400 401 const return_ty = @typeInfo(@TypeOf(S.foo)).@"fn".return_type.?; 402 try expectEqual(0, @typeInfo(@typeInfo(return_ty).error_union.error_set).error_set.error_names.?.len); 403 } 404 405 test "import passed byref to function in return type" { 406 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 407 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 408 409 const S = struct { 410 fn get() @import("std").ArrayList(i32) { 411 const x: @import("std").ArrayList(i32) = .empty; 412 return x; 413 } 414 }; 415 const list = S.get(); 416 try expect(list.items.len == 0); 417 } 418 419 test "implicit cast function to function ptr" { 420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 421 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 422 423 const S1 = struct { 424 export fn someFunctionThatReturnsAValue() c_int { 425 return 123; 426 } 427 }; 428 var fnPtr1: *const fn () callconv(.c) c_int = S1.someFunctionThatReturnsAValue; 429 _ = &fnPtr1; 430 try expect(fnPtr1() == 123); 431 const S2 = struct { 432 extern fn someFunctionThatReturnsAValue() c_int; 433 }; 434 var fnPtr2: *const fn () callconv(.c) c_int = S2.someFunctionThatReturnsAValue; 435 _ = &fnPtr2; 436 try expect(fnPtr2() == 123); 437 } 438 439 test "method call with optional and error union first param" { 440 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 441 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 442 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 443 444 const S = struct { 445 x: i32 = 1234, 446 447 fn opt(s: ?@This()) !void { 448 try expect(s.?.x == 1234); 449 } 450 fn errUnion(s: anyerror!@This()) !void { 451 try expect((try s).x == 1234); 452 } 453 }; 454 var s: S = .{}; 455 try s.opt(); 456 try s.errUnion(); 457 } 458 459 test "method call with optional pointer first param" { 460 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 461 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 462 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 463 464 const S = struct { 465 x: i32 = 1234, 466 467 fn method(s: ?*@This()) !void { 468 try expect(s.?.x == 1234); 469 } 470 }; 471 var s: S = .{}; 472 try s.method(); 473 const s_ptr = &s; 474 try s_ptr.method(); 475 } 476 477 test "using @ptrCast on function pointers" { 478 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 479 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 480 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 481 482 const S = struct { 483 const A = struct { data: [4]u8 }; 484 485 fn at(arr: *const A, index: usize) *const u8 { 486 return &arr.data[index]; 487 } 488 489 fn run() !void { 490 const a = A{ .data = "abcd".* }; 491 const casted_fn = @as(*const fn (*const anyopaque, usize) *const u8, @ptrCast(&at)); 492 const casted_impl = @as(*const anyopaque, @ptrCast(&a)); 493 const ptr = casted_fn(casted_impl, 2); 494 try expect(ptr.* == 'c'); 495 } 496 }; 497 498 try S.run(); 499 // https://github.com/ziglang/zig/issues/2626 500 // try comptime S.run(); 501 } 502 503 test "function returns function returning type" { 504 const S = struct { 505 fn a() fn () type { 506 return (struct { 507 fn b() type { 508 return u32; 509 } 510 }).b; 511 } 512 }; 513 try expect(S.a()() == u32); 514 } 515 516 test "peer type resolution of inferred error set with non-void payload" { 517 const S = struct { 518 fn openDataFile(mode: enum { read, write }) !u32 { 519 return switch (mode) { 520 .read => foo(), 521 .write => bar(), 522 }; 523 } 524 fn foo() error{ a, b }!u32 { 525 return 1; 526 } 527 fn bar() error{ c, d }!u32 { 528 return 2; 529 } 530 }; 531 try expect(try S.openDataFile(.read) == 1); 532 } 533 534 test "lazy values passed to anytype parameter" { 535 const A = struct { 536 a: u32, 537 fn foo(comptime a: anytype) !void { 538 try expect(a[0][0] == @sizeOf(@This())); 539 } 540 }; 541 try A.foo(.{[_]usize{@sizeOf(A)}}); 542 543 const B = struct { 544 fn foo(comptime a: anytype) !void { 545 try expect(a.x == 0); 546 } 547 }; 548 try B.foo(.{ .x = @sizeOf(B) }); 549 550 const C = struct {}; 551 try expect(@as(u32, @truncate(@sizeOf(C))) == 0); 552 553 const D = struct {}; 554 try expect(@sizeOf(D) << 1 == 0); 555 } 556 557 test "pass and return comptime-only types" { 558 const S = struct { 559 fn returnNull(comptime x: @TypeOf(null)) @TypeOf(null) { 560 return x; 561 } 562 fn returnUndefined(comptime x: @TypeOf(undefined)) @TypeOf(undefined) { 563 return x; 564 } 565 }; 566 567 try expectEqual(null, S.returnNull(null)); 568 try expectEqual(@as(u0, 0), S.returnUndefined(undefined)); 569 } 570 571 test "pointer to alias behaves same as pointer to function" { 572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 573 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 574 575 const S = struct { 576 fn foo() u32 { 577 return 11227; 578 } 579 const bar = foo; 580 }; 581 var a = &S.bar; 582 _ = &a; 583 try std.testing.expect(S.foo() == a()); 584 } 585 586 test "comptime parameters don't have to be marked comptime if only called at comptime" { 587 const S = struct { 588 fn foo(x: comptime_int, y: comptime_int) u32 { 589 return x + y; 590 } 591 }; 592 comptime std.debug.assert(S.foo(5, 6) == 11); 593 } 594 595 test "inline function with comptime-known comptime-only return type called at runtime" { 596 const S = struct { 597 inline fn foo(x: *i32, y: *const i32) type { 598 x.* = y.*; 599 return f32; 600 } 601 }; 602 var a: i32 = 0; 603 const b: i32 = 111; 604 const T = S.foo(&a, &b); 605 try expectEqual(111, a); 606 try expectEqual(f32, T); 607 } 608 609 test "address of function parameter is consistent" { 610 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 611 612 const S = struct { 613 fn paramAddrMatch(x: u8) bool { 614 return &x == &x; 615 } 616 }; 617 try expect(S.paramAddrMatch(0)); 618 comptime assert(S.paramAddrMatch(0)); 619 } 620 621 test "address of function parameter is consistent in other parameter type" { 622 const S = struct { 623 fn paramAddrMatch(comptime x: u8, y: if (&x != &x) unreachable else u8) void { 624 _ = y; 625 } 626 }; 627 S.paramAddrMatch(1, 2); 628 } 629 630 test "address of function parameter is consistent in function return type" { 631 const S = struct { 632 fn paramAddrMatch(comptime x: u8) if (&x != &x) unreachable else void {} 633 }; 634 S.paramAddrMatch(1); 635 } 636 637 test "function parameter self equality" { 638 const S = struct { 639 fn equal(x: u32) bool { 640 return x == x; 641 } 642 fn notEqual(x: u32) bool { 643 return x != x; 644 } 645 fn lessThan(x: u32) bool { 646 return x < x; 647 } 648 fn lessThanOrEqual(x: u32) bool { 649 return x <= x; 650 } 651 fn greaterThan(x: u32) bool { 652 return x > x; 653 } 654 fn greaterThanOrEqual(x: u32) bool { 655 return x >= x; 656 } 657 }; 658 try expect(S.equal(42)); 659 try expect(!S.notEqual(42)); 660 try expect(!S.lessThan(42)); 661 try expect(S.lessThanOrEqual(42)); 662 try expect(!S.greaterThan(42)); 663 try expect(S.greaterThanOrEqual(42)); 664 } 665 666 test "inline call propagates comptime-known argument to generic parameter and return types" { 667 const S = struct { 668 inline fn f(x: bool, y: if (x) u8 else u16) if (x) bool else u32 { 669 if (x) { 670 comptime assert(@TypeOf(y) == u8); 671 return y == 0; 672 } else { 673 comptime assert(@TypeOf(y) == u16); 674 return y * 10; 675 } 676 } 677 fn g(x: bool, y: if (x) u8 else u16) if (x) bool else u32 { 678 if (x) { 679 comptime assert(@TypeOf(y) == u8); 680 return y == 0; 681 } else { 682 comptime assert(@TypeOf(y) == u16); 683 return y * 10; 684 } 685 } 686 }; 687 688 const a0 = S.f(true, 200); // false 689 const a1 = S.f(false, 1234); // 12340 690 691 const b0 = @call(.always_inline, S.g, .{ true, 200 }); // false 692 const b1 = @call(.always_inline, S.g, .{ false, 1234 }); // 12340 693 694 comptime assert(@TypeOf(a0) == bool); 695 comptime assert(@TypeOf(b0) == bool); 696 try expect(a0 == false); 697 try expect(b0 == false); 698 699 comptime assert(@TypeOf(a1) == u32); 700 comptime assert(@TypeOf(b1) == u32); 701 try expect(a1 == 12340); 702 try expect(b1 == 12340); 703 } 704 705 test "inline function return type is evaluated at comptime" { 706 const S = struct { 707 inline fn assertComptimeAndRet(x: anytype) @TypeOf(x) { 708 if (!@inComptime()) comptime unreachable; 709 return x; 710 } 711 712 inline fn foo(val: anytype) assertComptimeAndRet(u16) { 713 return val; 714 } 715 }; 716 717 const result = S.foo(123); 718 comptime assert(@TypeOf(result) == u16); 719 try expect(result == 123); 720 } 721 722 test "coerce generic function making concrete parameter generic" { 723 const S = struct { 724 fn foo(_: anytype, x: u32) u32 { 725 comptime assert(@TypeOf(x) == u32); 726 return x; 727 } 728 }; 729 const coerced: fn (anytype, anytype) u32 = S.foo; 730 const result = coerced({}, 123); 731 try expect(result == 123); 732 } 733 734 test "coerce generic function making generic parameter concrete" { 735 const S = struct { 736 fn foo(_: anytype, x: anytype) u32 { 737 comptime assert(@TypeOf(x) == u32); 738 return x; 739 } 740 }; 741 const coerced: fn (anytype, u32) u32 = S.foo; 742 const result = coerced({}, 123); 743 try expect(result == 123); 744 } 745 746 test "return undefined pointer from function, directly and by expired local" { 747 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 748 749 const S = struct { 750 var global: i32 = 1; 751 752 fn returnGlobalPointer() *i32 { 753 return &global; 754 } 755 756 fn returnUndefPointer() *i32 { 757 return undefined; 758 } 759 760 /// Semantically equivalent to `returnUndefPointer`. 761 fn returnStackPointer() *i32 { 762 var stack_allocation: i32 = 1234; 763 const ptr = &stack_allocation; // defeats ast-check detection 764 return ptr; 765 } 766 }; 767 768 const ok_ptr = S.returnGlobalPointer(); 769 try expect(ok_ptr.* == 1); 770 const bad_ptr_1 = S.returnStackPointer(); 771 _ = bad_ptr_1; // dereferencing this would be illegal behavior 772 const bad_ptr_2 = S.returnStackPointer(); 773 _ = bad_ptr_2; // dereferencing this would be illegal behavior 774 } 775 776 test "a function that works at comptime but not runtime" { 777 const a = comptime testComptimeOnlyFn(1, 1); 778 try expect(a[0] == 1); 779 try expect(a[1] == 2); 780 } 781 782 fn testComptimeOnlyFn(x: u32, y: u32) [2]u8 { 783 const xa: [x]u8 = .{1}; 784 const ya: [y]u8 = .{2}; 785 return xa ++ ya; 786 } 787