| author | |
| committer | |
| log | ed5a5e22936e5d90b6c9d255b17076f0db45c040 |
| tree | 2fbb7435c4595de93277d0341373ba1ffd1982e4 |
| parent | 0d4a94f32fc71f81d54db038f013854b8e9f0ac4 |
6 files changed, 550 insertions(+), 531 deletions(-)
test/behavior.zig+2-1| ... | ... | @@ -25,6 +25,7 @@ test { |
| 25 | 25 | _ = @import("behavior/if.zig"); |
| 26 | 26 | _ = @import("behavior/math.zig"); |
| 27 | 27 | _ = @import("behavior/member_func.zig"); |
| 28 | _ = @import("behavior/optional.zig"); | |
| 28 | 29 | _ = @import("behavior/pointers.zig"); |
| 29 | 30 | _ = @import("behavior/slice.zig"); |
| 30 | 31 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| ... | ... | @@ -135,7 +136,7 @@ test { |
| 135 | 136 | _ = @import("behavior/muladd.zig"); |
| 136 | 137 | _ = @import("behavior/namespace_depends_on_compile_var.zig"); |
| 137 | 138 | _ = @import("behavior/null.zig"); |
| 138 | _ = @import("behavior/optional.zig"); | |
| 139 | _ = @import("behavior/optional_stage1.zig"); | |
| 139 | 140 | _ = @import("behavior/pointers_stage1.zig"); |
| 140 | 141 | _ = @import("behavior/popcount.zig"); |
| 141 | 142 | _ = @import("behavior/ptrcast.zig"); |
test/behavior/basic.zig+211| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const mem = std.mem; |
| 3 | 4 | const expect = std.testing.expect; |
| 4 | 5 | |
| ... | ... | @@ -192,6 +193,14 @@ fn testMemcpyMemset() !void { |
| 192 | 193 | const OpaqueA = opaque {}; |
| 193 | 194 | const OpaqueB = opaque {}; |
| 194 | 195 | |
| 196 | test "opaque types" { | |
| 197 | try expect(*OpaqueA != *OpaqueB); | |
| 198 | if (!builtin.zig_is_stage2) { | |
| 199 | try expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); | |
| 200 | try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); | |
| 201 | } | |
| 202 | } | |
| 203 | ||
| 195 | 204 | test "variable is allowed to be a pointer to an opaque type" { |
| 196 | 205 | var x: i32 = 1234; |
| 197 | 206 | _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x)); |
| ... | ... | @@ -200,3 +209,205 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { |
| 200 | 209 | var a = ptr; |
| 201 | 210 | return a; |
| 202 | 211 | } |
| 212 | ||
| 213 | const global_a: i32 = 1234; | |
| 214 | const global_b: *const i32 = &global_a; | |
| 215 | const global_c: *const f32 = @ptrCast(*const f32, global_b); | |
| 216 | test "compile time global reinterpret" { | |
| 217 | const d = @ptrCast(*const i32, global_c); | |
| 218 | try expect(d.* == 1234); | |
| 219 | } | |
| 220 | ||
| 221 | test "cast undefined" { | |
| 222 | const array: [100]u8 = undefined; | |
| 223 | const slice = @as([]const u8, &array); | |
| 224 | testCastUndefined(slice); | |
| 225 | } | |
| 226 | fn testCastUndefined(x: []const u8) void { | |
| 227 | _ = x; | |
| 228 | } | |
| 229 | ||
| 230 | test "implicit cast after unreachable" { | |
| 231 | try expect(outer() == 1234); | |
| 232 | } | |
| 233 | fn inner() i32 { | |
| 234 | return 1234; | |
| 235 | } | |
| 236 | fn outer() i64 { | |
| 237 | return inner(); | |
| 238 | } | |
| 239 | ||
| 240 | test "take address of parameter" { | |
| 241 | try testTakeAddressOfParameter(12.34); | |
| 242 | } | |
| 243 | fn testTakeAddressOfParameter(f: f32) !void { | |
| 244 | const f_ptr = &f; | |
| 245 | try expect(f_ptr.* == 12.34); | |
| 246 | } | |
| 247 | ||
| 248 | test "pointer to void return type" { | |
| 249 | testPointerToVoidReturnType() catch unreachable; | |
| 250 | } | |
| 251 | fn testPointerToVoidReturnType() anyerror!void { | |
| 252 | const a = testPointerToVoidReturnType2(); | |
| 253 | return a.*; | |
| 254 | } | |
| 255 | const test_pointer_to_void_return_type_x = void{}; | |
| 256 | fn testPointerToVoidReturnType2() *const void { | |
| 257 | return &test_pointer_to_void_return_type_x; | |
| 258 | } | |
| 259 | ||
| 260 | test "array 2D const double ptr" { | |
| 261 | const rect_2d_vertexes = [_][1]f32{ | |
| 262 | [_]f32{1.0}, | |
| 263 | [_]f32{2.0}, | |
| 264 | }; | |
| 265 | try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); | |
| 266 | } | |
| 267 | ||
| 268 | fn testArray2DConstDoublePtr(ptr: *const f32) !void { | |
| 269 | const ptr2 = @ptrCast([*]const f32, ptr); | |
| 270 | try expect(ptr2[0] == 1.0); | |
| 271 | try expect(ptr2[1] == 2.0); | |
| 272 | } | |
| 273 | ||
| 274 | test "double implicit cast in same expression" { | |
| 275 | var x = @as(i32, @as(u16, nine())); | |
| 276 | try expect(x == 9); | |
| 277 | } | |
| 278 | fn nine() u8 { | |
| 279 | return 9; | |
| 280 | } | |
| 281 | ||
| 282 | test "comptime if inside runtime while which unconditionally breaks" { | |
| 283 | testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | |
| 284 | comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | |
| 285 | } | |
| 286 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { | |
| 287 | while (cond) { | |
| 288 | if (false) {} | |
| 289 | break; | |
| 290 | } | |
| 291 | } | |
| 292 | ||
| 293 | test "implicit comptime while" { | |
| 294 | while (false) { | |
| 295 | @compileError("bad"); | |
| 296 | } | |
| 297 | } | |
| 298 | ||
| 299 | fn fnThatClosesOverLocalConst() type { | |
| 300 | const c = 1; | |
| 301 | return struct { | |
| 302 | fn g() i32 { | |
| 303 | return c; | |
| 304 | } | |
| 305 | }; | |
| 306 | } | |
| 307 | ||
| 308 | test "function closes over local const" { | |
| 309 | const x = fnThatClosesOverLocalConst().g(); | |
| 310 | try expect(x == 1); | |
| 311 | } | |
| 312 | ||
| 313 | test "volatile load and store" { | |
| 314 | var number: i32 = 1234; | |
| 315 | const ptr = @as(*volatile i32, &number); | |
| 316 | ptr.* += 1; | |
| 317 | try expect(ptr.* == 1235); | |
| 318 | } | |
| 319 | ||
| 320 | test "struct inside function" { | |
| 321 | try testStructInFn(); | |
| 322 | comptime try testStructInFn(); | |
| 323 | } | |
| 324 | ||
| 325 | fn testStructInFn() !void { | |
| 326 | const BlockKind = u32; | |
| 327 | ||
| 328 | const Block = struct { | |
| 329 | kind: BlockKind, | |
| 330 | }; | |
| 331 | ||
| 332 | var block = Block{ .kind = 1234 }; | |
| 333 | ||
| 334 | block.kind += 1; | |
| 335 | ||
| 336 | try expect(block.kind == 1235); | |
| 337 | } | |
| 338 | ||
| 339 | test "fn call returning scalar optional in equality expression" { | |
| 340 | try expect(getNull() == null); | |
| 341 | } | |
| 342 | ||
| 343 | fn getNull() ?*i32 { | |
| 344 | return null; | |
| 345 | } | |
| 346 | ||
| 347 | var global_foo: *i32 = undefined; | |
| 348 | ||
| 349 | test "global variable assignment with optional unwrapping with var initialized to undefined" { | |
| 350 | const S = struct { | |
| 351 | var data: i32 = 1234; | |
| 352 | fn foo() ?*i32 { | |
| 353 | return &data; | |
| 354 | } | |
| 355 | }; | |
| 356 | global_foo = S.foo() orelse { | |
| 357 | @panic("bad"); | |
| 358 | }; | |
| 359 | try expect(global_foo.* == 1234); | |
| 360 | } | |
| 361 | ||
| 362 | test "peer result location with typed parent, runtime condition, comptime prongs" { | |
| 363 | const S = struct { | |
| 364 | fn doTheTest(arg: i32) i32 { | |
| 365 | const st = Structy{ | |
| 366 | .bleh = if (arg == 1) 1 else 1, | |
| 367 | }; | |
| 368 | ||
| 369 | if (st.bleh == 1) | |
| 370 | return 1234; | |
| 371 | return 0; | |
| 372 | } | |
| 373 | ||
| 374 | const Structy = struct { | |
| 375 | bleh: i32, | |
| 376 | }; | |
| 377 | }; | |
| 378 | try expect(S.doTheTest(0) == 1234); | |
| 379 | try expect(S.doTheTest(1) == 1234); | |
| 380 | } | |
| 381 | ||
| 382 | fn ZA() type { | |
| 383 | return struct { | |
| 384 | b: B(), | |
| 385 | ||
| 386 | const Self = @This(); | |
| 387 | ||
| 388 | fn B() type { | |
| 389 | return struct { | |
| 390 | const Self = @This(); | |
| 391 | }; | |
| 392 | } | |
| 393 | }; | |
| 394 | } | |
| 395 | test "non-ambiguous reference of shadowed decls" { | |
| 396 | try expect(ZA().B().Self != ZA().Self); | |
| 397 | } | |
| 398 | ||
| 399 | test "use of declaration with same name as primitive" { | |
| 400 | const S = struct { | |
| 401 | const @"u8" = u16; | |
| 402 | const alias = @"u8"; | |
| 403 | }; | |
| 404 | const a: S.u8 = 300; | |
| 405 | try expect(a == 300); | |
| 406 | ||
| 407 | const b: S.alias = 300; | |
| 408 | try expect(b == 300); | |
| 409 | ||
| 410 | const @"u8" = u16; | |
| 411 | const c: @"u8" = 300; | |
| 412 | try expect(c == 300); | |
| 413 | } |
test/behavior/misc.zig+12-263| ... | ... | @@ -5,6 +5,8 @@ const expectEqualStrings = std.testing.expectEqualStrings; |
| 5 | 5 | const mem = std.mem; |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | |
| 8 | fn emptyFn() void {} | |
| 9 | ||
| 8 | 10 | test "constant equal function pointers" { |
| 9 | 11 | const alias = emptyFn; |
| 10 | 12 | try expect(comptime x: { |
| ... | ... | @@ -12,7 +14,16 @@ test "constant equal function pointers" { |
| 12 | 14 | }); |
| 13 | 15 | } |
| 14 | 16 | |
| 15 | fn emptyFn() void {} | |
| 17 | const addr1 = @ptrCast(*const u8, emptyFn); | |
| 18 | test "comptime cast fn to ptr" { | |
| 19 | const addr2 = @ptrCast(*const u8, emptyFn); | |
| 20 | comptime try expect(addr1 == addr2); | |
| 21 | } | |
| 22 | ||
| 23 | test "equality compare fn ptrs" { | |
| 24 | var a = emptyFn; | |
| 25 | try expect(a == a); | |
| 26 | } | |
| 16 | 27 | |
| 17 | 28 | test "string escapes" { |
| 18 | 29 | try expectEqualStrings("\"", "\x22"); |
| ... | ... | @@ -34,51 +45,12 @@ test "multiline string literal is null terminated" { |
| 34 | 45 | try expect(std.cstr.cmp(s1, s2) == 0); |
| 35 | 46 | } |
| 36 | 47 | |
| 37 | const global_a: i32 = 1234; | |
| 38 | const global_b: *const i32 = &global_a; | |
| 39 | const global_c: *const f32 = @ptrCast(*const f32, global_b); | |
| 40 | test "compile time global reinterpret" { | |
| 41 | const d = @ptrCast(*const i32, global_c); | |
| 42 | try expect(d.* == 1234); | |
| 43 | } | |
| 44 | ||
| 45 | 48 | test "explicit cast maybe pointers" { |
| 46 | 49 | const a: ?*i32 = undefined; |
| 47 | 50 | const b: ?*f32 = @ptrCast(?*f32, a); |
| 48 | 51 | _ = b; |
| 49 | 52 | } |
| 50 | 53 | |
| 51 | test "generic malloc free" { | |
| 52 | const a = memAlloc(u8, 10) catch unreachable; | |
| 53 | memFree(u8, a); | |
| 54 | } | |
| 55 | var some_mem: [100]u8 = undefined; | |
| 56 | fn memAlloc(comptime T: type, n: usize) anyerror![]T { | |
| 57 | return @ptrCast([*]T, &some_mem[0])[0..n]; | |
| 58 | } | |
| 59 | fn memFree(comptime T: type, memory: []T) void { | |
| 60 | _ = memory; | |
| 61 | } | |
| 62 | ||
| 63 | test "cast undefined" { | |
| 64 | const array: [100]u8 = undefined; | |
| 65 | const slice = @as([]const u8, &array); | |
| 66 | testCastUndefined(slice); | |
| 67 | } | |
| 68 | fn testCastUndefined(x: []const u8) void { | |
| 69 | _ = x; | |
| 70 | } | |
| 71 | ||
| 72 | test "implicit cast after unreachable" { | |
| 73 | try expect(outer() == 1234); | |
| 74 | } | |
| 75 | fn inner() i32 { | |
| 76 | return 1234; | |
| 77 | } | |
| 78 | fn outer() i64 { | |
| 79 | return inner(); | |
| 80 | } | |
| 81 | ||
| 82 | 54 | test "constant enum initialization with differing sizes" { |
| 83 | 55 | try test3_1(test3_foo); |
| 84 | 56 | try test3_2(test3_bar); |
| ... | ... | @@ -117,14 +89,6 @@ fn test3_2(f: Test3Foo) !void { |
| 117 | 89 | } |
| 118 | 90 | } |
| 119 | 91 | |
| 120 | test "take address of parameter" { | |
| 121 | try testTakeAddressOfParameter(12.34); | |
| 122 | } | |
| 123 | fn testTakeAddressOfParameter(f: f32) !void { | |
| 124 | const f_ptr = &f; | |
| 125 | try expect(f_ptr.* == 12.34); | |
| 126 | } | |
| 127 | ||
| 128 | 92 | test "pointer comparison" { |
| 129 | 93 | const a = @as([]const u8, "a"); |
| 130 | 94 | const b = &a; |
| ... | ... | @@ -153,40 +117,6 @@ test "string concatenation" { |
| 153 | 117 | try expect(b[len] == 0); |
| 154 | 118 | } |
| 155 | 119 | |
| 156 | test "pointer to void return type" { | |
| 157 | testPointerToVoidReturnType() catch unreachable; | |
| 158 | } | |
| 159 | fn testPointerToVoidReturnType() anyerror!void { | |
| 160 | const a = testPointerToVoidReturnType2(); | |
| 161 | return a.*; | |
| 162 | } | |
| 163 | const test_pointer_to_void_return_type_x = void{}; | |
| 164 | fn testPointerToVoidReturnType2() *const void { | |
| 165 | return &test_pointer_to_void_return_type_x; | |
| 166 | } | |
| 167 | ||
| 168 | test "array 2D const double ptr" { | |
| 169 | const rect_2d_vertexes = [_][1]f32{ | |
| 170 | [_]f32{1.0}, | |
| 171 | [_]f32{2.0}, | |
| 172 | }; | |
| 173 | try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); | |
| 174 | } | |
| 175 | ||
| 176 | fn testArray2DConstDoublePtr(ptr: *const f32) !void { | |
| 177 | const ptr2 = @ptrCast([*]const f32, ptr); | |
| 178 | try expect(ptr2[0] == 1.0); | |
| 179 | try expect(ptr2[1] == 2.0); | |
| 180 | } | |
| 181 | ||
| 182 | test "double implicit cast in same expression" { | |
| 183 | var x = @as(i32, @as(u16, nine())); | |
| 184 | try expect(x == 9); | |
| 185 | } | |
| 186 | fn nine() u8 { | |
| 187 | return 9; | |
| 188 | } | |
| 189 | ||
| 190 | 120 | test "global variable initialized to global variable array element" { |
| 191 | 121 | try expect(global_ptr == &gdt[0]); |
| 192 | 122 | } |
| ... | ... | @@ -206,45 +136,6 @@ export fn writeToVRam() void { |
| 206 | 136 | vram[0] = 'X'; |
| 207 | 137 | } |
| 208 | 138 | |
| 209 | const OpaqueA = opaque {}; | |
| 210 | const OpaqueB = opaque {}; | |
| 211 | test "opaque types" { | |
| 212 | try expect(*OpaqueA != *OpaqueB); | |
| 213 | try expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); | |
| 214 | try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); | |
| 215 | } | |
| 216 | ||
| 217 | test "comptime if inside runtime while which unconditionally breaks" { | |
| 218 | testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | |
| 219 | comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | |
| 220 | } | |
| 221 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { | |
| 222 | while (cond) { | |
| 223 | if (false) {} | |
| 224 | break; | |
| 225 | } | |
| 226 | } | |
| 227 | ||
| 228 | test "implicit comptime while" { | |
| 229 | while (false) { | |
| 230 | @compileError("bad"); | |
| 231 | } | |
| 232 | } | |
| 233 | ||
| 234 | fn fnThatClosesOverLocalConst() type { | |
| 235 | const c = 1; | |
| 236 | return struct { | |
| 237 | fn g() i32 { | |
| 238 | return c; | |
| 239 | } | |
| 240 | }; | |
| 241 | } | |
| 242 | ||
| 243 | test "function closes over local const" { | |
| 244 | const x = fnThatClosesOverLocalConst().g(); | |
| 245 | try expect(x == 1); | |
| 246 | } | |
| 247 | ||
| 248 | 139 | const PackedStruct = packed struct { |
| 249 | 140 | a: u8, |
| 250 | 141 | b: u8, |
| ... | ... | @@ -268,26 +159,6 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void { |
| 268 | 159 | } |
| 269 | 160 | } |
| 270 | 161 | |
| 271 | test "slicing zero length array" { | |
| 272 | const s1 = ""[0..]; | |
| 273 | const s2 = ([_]u32{})[0..]; | |
| 274 | try expect(s1.len == 0); | |
| 275 | try expect(s2.len == 0); | |
| 276 | try expect(mem.eql(u8, s1, "")); | |
| 277 | try expect(mem.eql(u32, s2, &[_]u32{})); | |
| 278 | } | |
| 279 | ||
| 280 | const addr1 = @ptrCast(*const u8, emptyFn); | |
| 281 | test "comptime cast fn to ptr" { | |
| 282 | const addr2 = @ptrCast(*const u8, emptyFn); | |
| 283 | comptime try expect(addr1 == addr2); | |
| 284 | } | |
| 285 | ||
| 286 | test "equality compare fn ptrs" { | |
| 287 | var a = emptyFn; | |
| 288 | try expect(a == a); | |
| 289 | } | |
| 290 | ||
| 291 | 162 | test "self reference through fn ptr field" { |
| 292 | 163 | const S = struct { |
| 293 | 164 | const A = struct { |
| ... | ... | @@ -304,52 +175,6 @@ test "self reference through fn ptr field" { |
| 304 | 175 | try expect(a.f(a) == 12); |
| 305 | 176 | } |
| 306 | 177 | |
| 307 | test "volatile load and store" { | |
| 308 | var number: i32 = 1234; | |
| 309 | const ptr = @as(*volatile i32, &number); | |
| 310 | ptr.* += 1; | |
| 311 | try expect(ptr.* == 1235); | |
| 312 | } | |
| 313 | ||
| 314 | test "slice string literal has correct type" { | |
| 315 | comptime { | |
| 316 | try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8); | |
| 317 | const array = [_]i32{ 1, 2, 3, 4 }; | |
| 318 | try expect(@TypeOf(array[0..]) == *const [4]i32); | |
| 319 | } | |
| 320 | var runtime_zero: usize = 0; | |
| 321 | comptime try expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8); | |
| 322 | const array = [_]i32{ 1, 2, 3, 4 }; | |
| 323 | comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32); | |
| 324 | } | |
| 325 | ||
| 326 | test "struct inside function" { | |
| 327 | try testStructInFn(); | |
| 328 | comptime try testStructInFn(); | |
| 329 | } | |
| 330 | ||
| 331 | fn testStructInFn() !void { | |
| 332 | const BlockKind = u32; | |
| 333 | ||
| 334 | const Block = struct { | |
| 335 | kind: BlockKind, | |
| 336 | }; | |
| 337 | ||
| 338 | var block = Block{ .kind = 1234 }; | |
| 339 | ||
| 340 | block.kind += 1; | |
| 341 | ||
| 342 | try expect(block.kind == 1235); | |
| 343 | } | |
| 344 | ||
| 345 | test "fn call returning scalar optional in equality expression" { | |
| 346 | try expect(getNull() == null); | |
| 347 | } | |
| 348 | ||
| 349 | fn getNull() ?*i32 { | |
| 350 | return null; | |
| 351 | } | |
| 352 | ||
| 353 | 178 | test "thread local variable" { |
| 354 | 179 | const S = struct { |
| 355 | 180 | threadlocal var t: i32 = 1234; |
| ... | ... | @@ -358,49 +183,6 @@ test "thread local variable" { |
| 358 | 183 | try expect(S.t == 1235); |
| 359 | 184 | } |
| 360 | 185 | |
| 361 | test "result location zero sized array inside struct field implicit cast to slice" { | |
| 362 | const E = struct { | |
| 363 | entries: []u32, | |
| 364 | }; | |
| 365 | var foo = E{ .entries = &[_]u32{} }; | |
| 366 | try expect(foo.entries.len == 0); | |
| 367 | } | |
| 368 | ||
| 369 | var global_foo: *i32 = undefined; | |
| 370 | ||
| 371 | test "global variable assignment with optional unwrapping with var initialized to undefined" { | |
| 372 | const S = struct { | |
| 373 | var data: i32 = 1234; | |
| 374 | fn foo() ?*i32 { | |
| 375 | return &data; | |
| 376 | } | |
| 377 | }; | |
| 378 | global_foo = S.foo() orelse { | |
| 379 | @panic("bad"); | |
| 380 | }; | |
| 381 | try expect(global_foo.* == 1234); | |
| 382 | } | |
| 383 | ||
| 384 | test "peer result location with typed parent, runtime condition, comptime prongs" { | |
| 385 | const S = struct { | |
| 386 | fn doTheTest(arg: i32) i32 { | |
| 387 | const st = Structy{ | |
| 388 | .bleh = if (arg == 1) 1 else 1, | |
| 389 | }; | |
| 390 | ||
| 391 | if (st.bleh == 1) | |
| 392 | return 1234; | |
| 393 | return 0; | |
| 394 | } | |
| 395 | ||
| 396 | const Structy = struct { | |
| 397 | bleh: i32, | |
| 398 | }; | |
| 399 | }; | |
| 400 | try expect(S.doTheTest(0) == 1234); | |
| 401 | try expect(S.doTheTest(1) == 1234); | |
| 402 | } | |
| 403 | ||
| 404 | 186 | test "nested optional field in struct" { |
| 405 | 187 | const S2 = struct { |
| 406 | 188 | y: u8, |
| ... | ... | @@ -462,36 +244,3 @@ test "lazy typeInfo value as generic parameter" { |
| 462 | 244 | }; |
| 463 | 245 | S.foo(@typeInfo(@TypeOf(.{}))); |
| 464 | 246 | } |
| 465 | ||
| 466 | fn ZA() type { | |
| 467 | return struct { | |
| 468 | b: B(), | |
| 469 | ||
| 470 | const Self = @This(); | |
| 471 | ||
| 472 | fn B() type { | |
| 473 | return struct { | |
| 474 | const Self = @This(); | |
| 475 | }; | |
| 476 | } | |
| 477 | }; | |
| 478 | } | |
| 479 | test "non-ambiguous reference of shadowed decls" { | |
| 480 | try expect(ZA().B().Self != ZA().Self); | |
| 481 | } | |
| 482 | ||
| 483 | test "use of declaration with same name as primitive" { | |
| 484 | const S = struct { | |
| 485 | const @"u8" = u16; | |
| 486 | const alias = @"u8"; | |
| 487 | }; | |
| 488 | const a: S.u8 = 300; | |
| 489 | try expect(a == 300); | |
| 490 | ||
| 491 | const b: S.alias = 300; | |
| 492 | try expect(b == 300); | |
| 493 | ||
| 494 | const @"u8" = u16; | |
| 495 | const c: @"u8" = 300; | |
| 496 | try expect(c == 300); | |
| 497 | } |
test/behavior/optional.zig-267| ... | ... | @@ -2,270 +2,3 @@ const std = @import("std"); |
| 2 | 2 | const testing = std.testing; |
| 3 | 3 | const expect = testing.expect; |
| 4 | 4 | const expectEqual = testing.expectEqual; |
| 5 | ||
| 6 | pub const EmptyStruct = struct {}; | |
| 7 | ||
| 8 | test "optional pointer to size zero struct" { | |
| 9 | var e = EmptyStruct{}; | |
| 10 | var o: ?*EmptyStruct = &e; | |
| 11 | try expect(o != null); | |
| 12 | } | |
| 13 | ||
| 14 | test "equality compare nullable pointers" { | |
| 15 | try testNullPtrsEql(); | |
| 16 | comptime try testNullPtrsEql(); | |
| 17 | } | |
| 18 | ||
| 19 | fn testNullPtrsEql() !void { | |
| 20 | var number: i32 = 1234; | |
| 21 | ||
| 22 | var x: ?*i32 = null; | |
| 23 | var y: ?*i32 = null; | |
| 24 | try expect(x == y); | |
| 25 | y = &number; | |
| 26 | try expect(x != y); | |
| 27 | try expect(x != &number); | |
| 28 | try expect(&number != x); | |
| 29 | x = &number; | |
| 30 | try expect(x == y); | |
| 31 | try expect(x == &number); | |
| 32 | try expect(&number == x); | |
| 33 | } | |
| 34 | ||
| 35 | test "address of unwrap optional" { | |
| 36 | const S = struct { | |
| 37 | const Foo = struct { | |
| 38 | a: i32, | |
| 39 | }; | |
| 40 | ||
| 41 | var global: ?Foo = null; | |
| 42 | ||
| 43 | pub fn getFoo() anyerror!*Foo { | |
| 44 | return &global.?; | |
| 45 | } | |
| 46 | }; | |
| 47 | S.global = S.Foo{ .a = 1234 }; | |
| 48 | const foo = S.getFoo() catch unreachable; | |
| 49 | try expect(foo.a == 1234); | |
| 50 | } | |
| 51 | ||
| 52 | test "equality compare optional with non-optional" { | |
| 53 | try test_cmp_optional_non_optional(); | |
| 54 | comptime try test_cmp_optional_non_optional(); | |
| 55 | } | |
| 56 | ||
| 57 | fn test_cmp_optional_non_optional() !void { | |
| 58 | var ten: i32 = 10; | |
| 59 | var opt_ten: ?i32 = 10; | |
| 60 | var five: i32 = 5; | |
| 61 | var int_n: ?i32 = null; | |
| 62 | ||
| 63 | try expect(int_n != ten); | |
| 64 | try expect(opt_ten == ten); | |
| 65 | try expect(opt_ten != five); | |
| 66 | ||
| 67 | // test evaluation is always lexical | |
| 68 | // ensure that the optional isn't always computed before the non-optional | |
| 69 | var mutable_state: i32 = 0; | |
| 70 | _ = blk1: { | |
| 71 | mutable_state += 1; | |
| 72 | break :blk1 @as(?f64, 10.0); | |
| 73 | } != blk2: { | |
| 74 | try expect(mutable_state == 1); | |
| 75 | break :blk2 @as(f64, 5.0); | |
| 76 | }; | |
| 77 | _ = blk1: { | |
| 78 | mutable_state += 1; | |
| 79 | break :blk1 @as(f64, 10.0); | |
| 80 | } != blk2: { | |
| 81 | try expect(mutable_state == 2); | |
| 82 | break :blk2 @as(?f64, 5.0); | |
| 83 | }; | |
| 84 | } | |
| 85 | ||
| 86 | test "passing an optional integer as a parameter" { | |
| 87 | const S = struct { | |
| 88 | fn entry() bool { | |
| 89 | var x: i32 = 1234; | |
| 90 | return foo(x); | |
| 91 | } | |
| 92 | ||
| 93 | fn foo(x: ?i32) bool { | |
| 94 | return x.? == 1234; | |
| 95 | } | |
| 96 | }; | |
| 97 | try expect(S.entry()); | |
| 98 | comptime try expect(S.entry()); | |
| 99 | } | |
| 100 | ||
| 101 | test "unwrap function call with optional pointer return value" { | |
| 102 | const S = struct { | |
| 103 | fn entry() !void { | |
| 104 | try expect(foo().?.* == 1234); | |
| 105 | try expect(bar() == null); | |
| 106 | } | |
| 107 | const global: i32 = 1234; | |
| 108 | fn foo() ?*const i32 { | |
| 109 | return &global; | |
| 110 | } | |
| 111 | fn bar() ?*i32 { | |
| 112 | return null; | |
| 113 | } | |
| 114 | }; | |
| 115 | try S.entry(); | |
| 116 | comptime try S.entry(); | |
| 117 | } | |
| 118 | ||
| 119 | test "nested orelse" { | |
| 120 | const S = struct { | |
| 121 | fn entry() !void { | |
| 122 | try expect(func() == null); | |
| 123 | } | |
| 124 | fn maybe() ?Foo { | |
| 125 | return null; | |
| 126 | } | |
| 127 | fn func() ?Foo { | |
| 128 | const x = maybe() orelse | |
| 129 | maybe() orelse | |
| 130 | return null; | |
| 131 | _ = x; | |
| 132 | unreachable; | |
| 133 | } | |
| 134 | const Foo = struct { | |
| 135 | field: i32, | |
| 136 | }; | |
| 137 | }; | |
| 138 | try S.entry(); | |
| 139 | comptime try S.entry(); | |
| 140 | } | |
| 141 | ||
| 142 | test "self-referential struct through a slice of optional" { | |
| 143 | const S = struct { | |
| 144 | const Node = struct { | |
| 145 | children: []?Node, | |
| 146 | data: ?u8, | |
| 147 | ||
| 148 | fn new() Node { | |
| 149 | return Node{ | |
| 150 | .children = undefined, | |
| 151 | .data = null, | |
| 152 | }; | |
| 153 | } | |
| 154 | }; | |
| 155 | }; | |
| 156 | ||
| 157 | var n = S.Node.new(); | |
| 158 | try expect(n.data == null); | |
| 159 | } | |
| 160 | ||
| 161 | test "assigning to an unwrapped optional field in an inline loop" { | |
| 162 | comptime var maybe_pos_arg: ?comptime_int = null; | |
| 163 | inline for ("ab") |x| { | |
| 164 | _ = x; | |
| 165 | maybe_pos_arg = 0; | |
| 166 | if (maybe_pos_arg.? != 0) { | |
| 167 | @compileError("bad"); | |
| 168 | } | |
| 169 | maybe_pos_arg.? = 10; | |
| 170 | } | |
| 171 | } | |
| 172 | ||
| 173 | test "coerce an anon struct literal to optional struct" { | |
| 174 | const S = struct { | |
| 175 | const Struct = struct { | |
| 176 | field: u32, | |
| 177 | }; | |
| 178 | fn doTheTest() !void { | |
| 179 | var maybe_dims: ?Struct = null; | |
| 180 | maybe_dims = .{ .field = 1 }; | |
| 181 | try expect(maybe_dims.?.field == 1); | |
| 182 | } | |
| 183 | }; | |
| 184 | try S.doTheTest(); | |
| 185 | comptime try S.doTheTest(); | |
| 186 | } | |
| 187 | ||
| 188 | test "optional with void type" { | |
| 189 | const Foo = struct { | |
| 190 | x: ?void, | |
| 191 | }; | |
| 192 | var x = Foo{ .x = null }; | |
| 193 | try expect(x.x == null); | |
| 194 | } | |
| 195 | ||
| 196 | test "0-bit child type coerced to optional return ptr result location" { | |
| 197 | const S = struct { | |
| 198 | fn doTheTest() !void { | |
| 199 | var y = Foo{}; | |
| 200 | var z = y.thing(); | |
| 201 | try expect(z != null); | |
| 202 | } | |
| 203 | ||
| 204 | const Foo = struct { | |
| 205 | pub const Bar = struct { | |
| 206 | field: *Foo, | |
| 207 | }; | |
| 208 | ||
| 209 | pub fn thing(self: *Foo) ?Bar { | |
| 210 | return Bar{ .field = self }; | |
| 211 | } | |
| 212 | }; | |
| 213 | }; | |
| 214 | try S.doTheTest(); | |
| 215 | comptime try S.doTheTest(); | |
| 216 | } | |
| 217 | ||
| 218 | test "0-bit child type coerced to optional" { | |
| 219 | const S = struct { | |
| 220 | fn doTheTest() !void { | |
| 221 | var it: Foo = .{ | |
| 222 | .list = undefined, | |
| 223 | }; | |
| 224 | try expect(it.foo() != null); | |
| 225 | } | |
| 226 | ||
| 227 | const Empty = struct {}; | |
| 228 | const Foo = struct { | |
| 229 | list: [10]Empty, | |
| 230 | ||
| 231 | fn foo(self: *Foo) ?*Empty { | |
| 232 | const data = &self.list[0]; | |
| 233 | return data; | |
| 234 | } | |
| 235 | }; | |
| 236 | }; | |
| 237 | try S.doTheTest(); | |
| 238 | comptime try S.doTheTest(); | |
| 239 | } | |
| 240 | ||
| 241 | test "array of optional unaligned types" { | |
| 242 | const Enum = enum { one, two, three }; | |
| 243 | ||
| 244 | const SomeUnion = union(enum) { | |
| 245 | Num: Enum, | |
| 246 | Other: u32, | |
| 247 | }; | |
| 248 | ||
| 249 | const values = [_]?SomeUnion{ | |
| 250 | SomeUnion{ .Num = .one }, | |
| 251 | SomeUnion{ .Num = .two }, | |
| 252 | SomeUnion{ .Num = .three }, | |
| 253 | SomeUnion{ .Num = .one }, | |
| 254 | SomeUnion{ .Num = .two }, | |
| 255 | SomeUnion{ .Num = .three }, | |
| 256 | }; | |
| 257 | ||
| 258 | // The index must be a runtime value | |
| 259 | var i: usize = 0; | |
| 260 | try expectEqual(Enum.one, values[i].?.Num); | |
| 261 | i += 1; | |
| 262 | try expectEqual(Enum.two, values[i].?.Num); | |
| 263 | i += 1; | |
| 264 | try expectEqual(Enum.three, values[i].?.Num); | |
| 265 | i += 1; | |
| 266 | try expectEqual(Enum.one, values[i].?.Num); | |
| 267 | i += 1; | |
| 268 | try expectEqual(Enum.two, values[i].?.Num); | |
| 269 | i += 1; | |
| 270 | try expectEqual(Enum.three, values[i].?.Num); | |
| 271 | } |
test/behavior/optional_stage1.zig created+284| ... | ... | @@ -0,0 +1,284 @@ |
| 1 | const std = @import("std"); | |
| 2 | const testing = std.testing; | |
| 3 | const expect = testing.expect; | |
| 4 | const expectEqual = testing.expectEqual; | |
| 5 | ||
| 6 | pub const EmptyStruct = struct {}; | |
| 7 | ||
| 8 | test "optional pointer to size zero struct" { | |
| 9 | var e = EmptyStruct{}; | |
| 10 | var o: ?*EmptyStruct = &e; | |
| 11 | try expect(o != null); | |
| 12 | } | |
| 13 | ||
| 14 | test "equality compare nullable pointers" { | |
| 15 | try testNullPtrsEql(); | |
| 16 | comptime try testNullPtrsEql(); | |
| 17 | } | |
| 18 | ||
| 19 | fn testNullPtrsEql() !void { | |
| 20 | var number: i32 = 1234; | |
| 21 | ||
| 22 | var x: ?*i32 = null; | |
| 23 | var y: ?*i32 = null; | |
| 24 | try expect(x == y); | |
| 25 | y = &number; | |
| 26 | try expect(x != y); | |
| 27 | try expect(x != &number); | |
| 28 | try expect(&number != x); | |
| 29 | x = &number; | |
| 30 | try expect(x == y); | |
| 31 | try expect(x == &number); | |
| 32 | try expect(&number == x); | |
| 33 | } | |
| 34 | ||
| 35 | test "address of unwrap optional" { | |
| 36 | const S = struct { | |
| 37 | const Foo = struct { | |
| 38 | a: i32, | |
| 39 | }; | |
| 40 | ||
| 41 | var global: ?Foo = null; | |
| 42 | ||
| 43 | pub fn getFoo() anyerror!*Foo { | |
| 44 | return &global.?; | |
| 45 | } | |
| 46 | }; | |
| 47 | S.global = S.Foo{ .a = 1234 }; | |
| 48 | const foo = S.getFoo() catch unreachable; | |
| 49 | try expect(foo.a == 1234); | |
| 50 | } | |
| 51 | ||
| 52 | test "equality compare optional with non-optional" { | |
| 53 | try test_cmp_optional_non_optional(); | |
| 54 | comptime try test_cmp_optional_non_optional(); | |
| 55 | } | |
| 56 | ||
| 57 | fn test_cmp_optional_non_optional() !void { | |
| 58 | var ten: i32 = 10; | |
| 59 | var opt_ten: ?i32 = 10; | |
| 60 | var five: i32 = 5; | |
| 61 | var int_n: ?i32 = null; | |
| 62 | ||
| 63 | try expect(int_n != ten); | |
| 64 | try expect(opt_ten == ten); | |
| 65 | try expect(opt_ten != five); | |
| 66 | ||
| 67 | // test evaluation is always lexical | |
| 68 | // ensure that the optional isn't always computed before the non-optional | |
| 69 | var mutable_state: i32 = 0; | |
| 70 | _ = blk1: { | |
| 71 | mutable_state += 1; | |
| 72 | break :blk1 @as(?f64, 10.0); | |
| 73 | } != blk2: { | |
| 74 | try expect(mutable_state == 1); | |
| 75 | break :blk2 @as(f64, 5.0); | |
| 76 | }; | |
| 77 | _ = blk1: { | |
| 78 | mutable_state += 1; | |
| 79 | break :blk1 @as(f64, 10.0); | |
| 80 | } != blk2: { | |
| 81 | try expect(mutable_state == 2); | |
| 82 | break :blk2 @as(?f64, 5.0); | |
| 83 | }; | |
| 84 | } | |
| 85 | ||
| 86 | test "passing an optional integer as a parameter" { | |
| 87 | const S = struct { | |
| 88 | fn entry() bool { | |
| 89 | var x: i32 = 1234; | |
| 90 | return foo(x); | |
| 91 | } | |
| 92 | ||
| 93 | fn foo(x: ?i32) bool { | |
| 94 | return x.? == 1234; | |
| 95 | } | |
| 96 | }; | |
| 97 | try expect(S.entry()); | |
| 98 | comptime try expect(S.entry()); | |
| 99 | } | |
| 100 | ||
| 101 | test "unwrap function call with optional pointer return value" { | |
| 102 | const S = struct { | |
| 103 | fn entry() !void { | |
| 104 | try expect(foo().?.* == 1234); | |
| 105 | try expect(bar() == null); | |
| 106 | } | |
| 107 | const global: i32 = 1234; | |
| 108 | fn foo() ?*const i32 { | |
| 109 | return &global; | |
| 110 | } | |
| 111 | fn bar() ?*i32 { | |
| 112 | return null; | |
| 113 | } | |
| 114 | }; | |
| 115 | try S.entry(); | |
| 116 | comptime try S.entry(); | |
| 117 | } | |
| 118 | ||
| 119 | test "nested orelse" { | |
| 120 | const S = struct { | |
| 121 | fn entry() !void { | |
| 122 | try expect(func() == null); | |
| 123 | } | |
| 124 | fn maybe() ?Foo { | |
| 125 | return null; | |
| 126 | } | |
| 127 | fn func() ?Foo { | |
| 128 | const x = maybe() orelse | |
| 129 | maybe() orelse | |
| 130 | return null; | |
| 131 | _ = x; | |
| 132 | unreachable; | |
| 133 | } | |
| 134 | const Foo = struct { | |
| 135 | field: i32, | |
| 136 | }; | |
| 137 | }; | |
| 138 | try S.entry(); | |
| 139 | comptime try S.entry(); | |
| 140 | } | |
| 141 | ||
| 142 | test "self-referential struct through a slice of optional" { | |
| 143 | const S = struct { | |
| 144 | const Node = struct { | |
| 145 | children: []?Node, | |
| 146 | data: ?u8, | |
| 147 | ||
| 148 | fn new() Node { | |
| 149 | return Node{ | |
| 150 | .children = undefined, | |
| 151 | .data = null, | |
| 152 | }; | |
| 153 | } | |
| 154 | }; | |
| 155 | }; | |
| 156 | ||
| 157 | var n = S.Node.new(); | |
| 158 | try expect(n.data == null); | |
| 159 | } | |
| 160 | ||
| 161 | test "assigning to an unwrapped optional field in an inline loop" { | |
| 162 | comptime var maybe_pos_arg: ?comptime_int = null; | |
| 163 | inline for ("ab") |x| { | |
| 164 | _ = x; | |
| 165 | maybe_pos_arg = 0; | |
| 166 | if (maybe_pos_arg.? != 0) { | |
| 167 | @compileError("bad"); | |
| 168 | } | |
| 169 | maybe_pos_arg.? = 10; | |
| 170 | } | |
| 171 | } | |
| 172 | ||
| 173 | test "coerce an anon struct literal to optional struct" { | |
| 174 | const S = struct { | |
| 175 | const Struct = struct { | |
| 176 | field: u32, | |
| 177 | }; | |
| 178 | fn doTheTest() !void { | |
| 179 | var maybe_dims: ?Struct = null; | |
| 180 | maybe_dims = .{ .field = 1 }; | |
| 181 | try expect(maybe_dims.?.field == 1); | |
| 182 | } | |
| 183 | }; | |
| 184 | try S.doTheTest(); | |
| 185 | comptime try S.doTheTest(); | |
| 186 | } | |
| 187 | ||
| 188 | test "optional with void type" { | |
| 189 | const Foo = struct { | |
| 190 | x: ?void, | |
| 191 | }; | |
| 192 | var x = Foo{ .x = null }; | |
| 193 | try expect(x.x == null); | |
| 194 | } | |
| 195 | ||
| 196 | test "0-bit child type coerced to optional return ptr result location" { | |
| 197 | const S = struct { | |
| 198 | fn doTheTest() !void { | |
| 199 | var y = Foo{}; | |
| 200 | var z = y.thing(); | |
| 201 | try expect(z != null); | |
| 202 | } | |
| 203 | ||
| 204 | const Foo = struct { | |
| 205 | pub const Bar = struct { | |
| 206 | field: *Foo, | |
| 207 | }; | |
| 208 | ||
| 209 | pub fn thing(self: *Foo) ?Bar { | |
| 210 | return Bar{ .field = self }; | |
| 211 | } | |
| 212 | }; | |
| 213 | }; | |
| 214 | try S.doTheTest(); | |
| 215 | comptime try S.doTheTest(); | |
| 216 | } | |
| 217 | ||
| 218 | test "0-bit child type coerced to optional" { | |
| 219 | const S = struct { | |
| 220 | fn doTheTest() !void { | |
| 221 | var it: Foo = .{ | |
| 222 | .list = undefined, | |
| 223 | }; | |
| 224 | try expect(it.foo() != null); | |
| 225 | } | |
| 226 | ||
| 227 | const Empty = struct {}; | |
| 228 | const Foo = struct { | |
| 229 | list: [10]Empty, | |
| 230 | ||
| 231 | fn foo(self: *Foo) ?*Empty { | |
| 232 | const data = &self.list[0]; | |
| 233 | return data; | |
| 234 | } | |
| 235 | }; | |
| 236 | }; | |
| 237 | try S.doTheTest(); | |
| 238 | comptime try S.doTheTest(); | |
| 239 | } | |
| 240 | ||
| 241 | test "array of optional unaligned types" { | |
| 242 | const Enum = enum { one, two, three }; | |
| 243 | ||
| 244 | const SomeUnion = union(enum) { | |
| 245 | Num: Enum, | |
| 246 | Other: u32, | |
| 247 | }; | |
| 248 | ||
| 249 | const values = [_]?SomeUnion{ | |
| 250 | SomeUnion{ .Num = .one }, | |
| 251 | SomeUnion{ .Num = .two }, | |
| 252 | SomeUnion{ .Num = .three }, | |
| 253 | SomeUnion{ .Num = .one }, | |
| 254 | SomeUnion{ .Num = .two }, | |
| 255 | SomeUnion{ .Num = .three }, | |
| 256 | }; | |
| 257 | ||
| 258 | // The index must be a runtime value | |
| 259 | var i: usize = 0; | |
| 260 | try expectEqual(Enum.one, values[i].?.Num); | |
| 261 | i += 1; | |
| 262 | try expectEqual(Enum.two, values[i].?.Num); | |
| 263 | i += 1; | |
| 264 | try expectEqual(Enum.three, values[i].?.Num); | |
| 265 | i += 1; | |
| 266 | try expectEqual(Enum.one, values[i].?.Num); | |
| 267 | i += 1; | |
| 268 | try expectEqual(Enum.two, values[i].?.Num); | |
| 269 | i += 1; | |
| 270 | try expectEqual(Enum.three, values[i].?.Num); | |
| 271 | } | |
| 272 | ||
| 273 | test "nested optional field in struct" { | |
| 274 | const S2 = struct { | |
| 275 | y: u8, | |
| 276 | }; | |
| 277 | const S1 = struct { | |
| 278 | x: ?S2, | |
| 279 | }; | |
| 280 | var s = S1{ | |
| 281 | .x = S2{ .y = 127 }, | |
| 282 | }; | |
| 283 | try expect(s.x.?.y == 127); | |
| 284 | } |
test/behavior/slice_stage1.zig+41| ... | ... | @@ -20,6 +20,47 @@ test "slicing" { |
| 20 | 20 | if (slice_rest.len != 10) unreachable; |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | test "slicing zero length array" { | |
| 24 | const s1 = ""[0..]; | |
| 25 | const s2 = ([_]u32{})[0..]; | |
| 26 | try expect(s1.len == 0); | |
| 27 | try expect(s2.len == 0); | |
| 28 | try expect(mem.eql(u8, s1, "")); | |
| 29 | try expect(mem.eql(u32, s2, &[_]u32{})); | |
| 30 | } | |
| 31 | ||
| 32 | test "slice string literal has correct type" { | |
| 33 | comptime { | |
| 34 | try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8); | |
| 35 | const array = [_]i32{ 1, 2, 3, 4 }; | |
| 36 | try expect(@TypeOf(array[0..]) == *const [4]i32); | |
| 37 | } | |
| 38 | var runtime_zero: usize = 0; | |
| 39 | comptime try expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8); | |
| 40 | const array = [_]i32{ 1, 2, 3, 4 }; | |
| 41 | comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32); | |
| 42 | } | |
| 43 | ||
| 44 | test "generic malloc free" { | |
| 45 | const a = memAlloc(u8, 10) catch unreachable; | |
| 46 | memFree(u8, a); | |
| 47 | } | |
| 48 | var some_mem: [100]u8 = undefined; | |
| 49 | fn memAlloc(comptime T: type, n: usize) anyerror![]T { | |
| 50 | return @ptrCast([*]T, &some_mem[0])[0..n]; | |
| 51 | } | |
| 52 | fn memFree(comptime T: type, memory: []T) void { | |
| 53 | _ = memory; | |
| 54 | } | |
| 55 | ||
| 56 | test "result location zero sized array inside struct field implicit cast to slice" { | |
| 57 | const E = struct { | |
| 58 | entries: []u32, | |
| 59 | }; | |
| 60 | var foo = E{ .entries = &[_]u32{} }; | |
| 61 | try expect(foo.entries.len == 0); | |
| 62 | } | |
| 63 | ||
| 23 | 64 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; |
| 24 | 65 | const y = x[0x100..]; |
| 25 | 66 | test "compile time slice of pointer to hard coded address" { |