| ... | ... | @@ -4352,42 +4352,191 @@ test "float widening" { |
| 4352 | 4352 | } |
| 4353 | 4353 | {#code_end#} |
| 4354 | 4354 | {#header_close#} |
| 4355 | | {#header_open|Implicit Cast: Arrays#} |
| 4356 | | <p>TODO: [N]T to []const T</p> |
| 4357 | | <p>TODO: *const [N]T to []const T</p> |
| 4358 | | <p>TODO: [N]T to *const []const T</p> |
| 4359 | | <p>TODO: [N]T to ?[]const T</p> |
| 4360 | | <p>TODO: *[N]T to []T</p> |
| 4361 | | <p>TODO: *[N]T to [*]T</p> |
| 4362 | | <p>TODO: *[N]T to ?[*]T</p> |
| 4363 | | <p>TODO: *T to *[1]T</p> |
| 4364 | | <p>TODO: [N]T to E![]const T</p> |
| 4355 | {#header_open|Implicit Cast: Arrays and Pointers#} |
| 4356 | {#code_begin|test#} |
| 4357 | const std = @import("std"); |
| 4358 | const assert = std.debug.assert; |
| 4359 | |
| 4360 | // This cast exists primarily so that string literals can be |
| 4361 | // passed to functions that accept const slices. However |
| 4362 | // it is probably going to be removed from the language when |
| 4363 | // https://github.com/ziglang/zig/issues/265 is implemented. |
| 4364 | test "[N]T to []const T" { |
| 4365 | var x1: []const u8 = "hello"; |
| 4366 | var x2: []const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 }; |
| 4367 | assert(std.mem.eql(u8, x1, x2)); |
| 4368 | |
| 4369 | var y: []const f32 = [2]f32{ 1.2, 3.4 }; |
| 4370 | assert(y[0] == 1.2); |
| 4371 | } |
| 4372 | |
| 4373 | // Likewise, it works when the destination type is an error union. |
| 4374 | test "[N]T to E![]const T" { |
| 4375 | var x1: anyerror![]const u8 = "hello"; |
| 4376 | var x2: anyerror![]const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 }; |
| 4377 | assert(std.mem.eql(u8, try x1, try x2)); |
| 4378 | |
| 4379 | var y: anyerror![]const f32 = [2]f32{ 1.2, 3.4 }; |
| 4380 | assert((try y)[0] == 1.2); |
| 4381 | } |
| 4382 | |
| 4383 | // Likewise, it works when the destination type is an optional. |
| 4384 | test "[N]T to ?[]const T" { |
| 4385 | var x1: ?[]const u8 = "hello"; |
| 4386 | var x2: ?[]const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 }; |
| 4387 | assert(std.mem.eql(u8, x1.?, x2.?)); |
| 4388 | |
| 4389 | var y: ?[]const f32 = [2]f32{ 1.2, 3.4 }; |
| 4390 | assert(y.?[0] == 1.2); |
| 4391 | } |
| 4392 | |
| 4393 | // In this cast, the array length becomes the slice length. |
| 4394 | test "*[N]T to []T" { |
| 4395 | var buf: [5]u8 = "hello"; |
| 4396 | const x: []u8 = &buf; |
| 4397 | assert(std.mem.eql(u8, x, "hello")); |
| 4398 | |
| 4399 | const buf2 = [2]f32{ 1.2, 3.4 }; |
| 4400 | const x2: []const f32 = &buf2; |
| 4401 | assert(std.mem.eql(f32, x2, [2]f32{ 1.2, 3.4 })); |
| 4402 | } |
| 4403 | |
| 4404 | // Single-item pointers to arrays can be implicitly casted to |
| 4405 | // unknown length pointers. |
| 4406 | test "*[N]T to [*]T" { |
| 4407 | var buf: [5]u8 = "hello"; |
| 4408 | const x: [*]u8 = &buf; |
| 4409 | assert(x[4] == 'o'); |
| 4410 | // x[5] would be an uncaught out of bounds pointer dereference! |
| 4411 | } |
| 4412 | |
| 4413 | // Likewise, it works when the destination type is an optional. |
| 4414 | test "*[N]T to ?[*]T" { |
| 4415 | var buf: [5]u8 = "hello"; |
| 4416 | const x: ?[*]u8 = &buf; |
| 4417 | assert(x.?[4] == 'o'); |
| 4418 | } |
| 4419 | |
| 4420 | // Single-item pointers can be cast to len-1 single-item arrays. |
| 4421 | test "*T to *[1]T" { |
| 4422 | var x: i32 = 1234; |
| 4423 | const y: *[1]i32 = &x; |
| 4424 | const z: [*]i32 = y; |
| 4425 | assert(z[0] == 1234); |
| 4426 | } |
| 4427 | {#code_end#} |
| 4428 | {#see_also|C Pointers#} |
| 4365 | 4429 | {#header_close#} |
| 4366 | 4430 | {#header_open|Implicit Cast: Optionals#} |
| 4367 | | <p>TODO: T to ?T</p> |
| 4368 | | <p>TODO: T to E!?T</p> |
| 4369 | | <p>TODO: null to ?T</p> |
| 4370 | | {#header_close#} |
| 4371 | | {#header_open|Implicit Cast: T to E!T#} |
| 4372 | | <p>TODO</p> |
| 4373 | | {#header_close#} |
| 4374 | | {#header_open|Implicit Cast: E to E!T#} |
| 4375 | | <p>TODO</p> |
| 4431 | <p> |
| 4432 | The payload type of {#link|Optionals#}, as well as {#link|null#}, implicitly cast to the optional type. |
| 4433 | </p> |
| 4434 | {#code_begin|test#} |
| 4435 | const std = @import("std"); |
| 4436 | const assert = std.debug.assert; |
| 4437 | |
| 4438 | test "implicit casting to optionals" { |
| 4439 | const x: ?i32 = 1234; |
| 4440 | const y: ?i32 = null; |
| 4441 | |
| 4442 | assert(x.? == 1234); |
| 4443 | assert(y == null); |
| 4444 | } |
| 4445 | {#code_end#} |
| 4446 | <p>It works nested inside the {#link|Error Union Type#}, too:</p> |
| 4447 | {#code_begin|test#} |
| 4448 | const std = @import("std"); |
| 4449 | const assert = std.debug.assert; |
| 4450 | |
| 4451 | test "implicit casting to optionals wrapped in error union" { |
| 4452 | const x: anyerror!?i32 = 1234; |
| 4453 | const y: anyerror!?i32 = null; |
| 4454 | |
| 4455 | assert((try x).? == 1234); |
| 4456 | assert((try y) == null); |
| 4457 | } |
| 4458 | {#code_end#} |
| 4376 | 4459 | {#header_close#} |
| 4377 | | {#header_open|Implicit Cast: compile-time known numbers#} |
| 4378 | | <p>TODO</p> |
| 4460 | {#header_open|Implicit Cast: Error Unions#} |
| 4461 | <p>The the payload type of an {#link|Error Union Type#} as well as the {#link|Error Set Type#} |
| 4462 | implicitly cast to the error union type: |
| 4463 | </p> |
| 4464 | {#code_begin|test#} |
| 4465 | const std = @import("std"); |
| 4466 | const assert = std.debug.assert; |
| 4467 | |
| 4468 | test "implicit casting to error unions" { |
| 4469 | const x: anyerror!i32 = 1234; |
| 4470 | const y: anyerror!i32 = error.Failure; |
| 4471 | |
| 4472 | assert((try x) == 1234); |
| 4473 | std.testing.expectError(error.Failure, y); |
| 4474 | } |
| 4475 | {#code_end#} |
| 4379 | 4476 | {#header_close#} |
| 4380 | | {#header_open|Implicit Cast: union to enum#} |
| 4381 | | <p>TODO</p> |
| 4477 | {#header_open|Implicit Cast: Compile-Time Known Numbers#} |
| 4478 | <p>When a number is {#link|comptime#}-known to be representable in the destination type, |
| 4479 | it may be implicitly casted: |
| 4480 | </p> |
| 4481 | {#code_begin|test#} |
| 4482 | const std = @import("std"); |
| 4483 | const assert = std.debug.assert; |
| 4484 | |
| 4485 | test "implicit casting large integer type to smaller one when value is comptime known to fit" { |
| 4486 | const x: u64 = 255; |
| 4487 | const y: u8 = x; |
| 4488 | assert(y == 255); |
| 4489 | } |
| 4490 | {#code_end#} |
| 4382 | 4491 | {#header_close#} |
| 4383 | | {#header_open|Implicit Cast: enum to union#} |
| 4384 | | <p>TODO</p> |
| 4492 | {#header_open|Implicit Cast: unions and enums#} |
| 4493 | <p>Tagged unions can be implicitly cast to enums, and enums can be implicitly casted to tagged unions |
| 4494 | when they are {#link|comptime#}-known to be a field of the union that has only one possible value, such as |
| 4495 | {#link|void#}: |
| 4496 | </p> |
| 4497 | {#code_begin|test#} |
| 4498 | const std = @import("std"); |
| 4499 | const assert = std.debug.assert; |
| 4500 | |
| 4501 | const E = enum { |
| 4502 | One, |
| 4503 | Two, |
| 4504 | Three, |
| 4505 | }; |
| 4506 | |
| 4507 | const U = union(E) { |
| 4508 | One: i32, |
| 4509 | Two: f32, |
| 4510 | Three, |
| 4511 | }; |
| 4512 | |
| 4513 | test "implicit casting between unions and enums" { |
| 4514 | var u = U{ .Two = 12.34 }; |
| 4515 | var e: E = u; |
| 4516 | assert(e == E.Two); |
| 4517 | |
| 4518 | const three = E.Three; |
| 4519 | var another_u: U = three; |
| 4520 | assert(another_u == E.Three); |
| 4521 | } |
| 4522 | {#code_end#} |
| 4523 | {#see_also|union|enum#} |
| 4385 | 4524 | {#header_close#} |
| 4386 | | {#header_open|Implicit Cast: T to *T when @sizeOf(T) == 0#} |
| 4387 | | <p>TODO</p> |
| 4525 | {#header_open|Implicit Cast: Zero Bit Types#} |
| 4526 | <p>{#link|Zero Bit Types#} may be implicitly casted to single-item {#link|Pointers#}, |
| 4527 | regardless of const.</p> |
| 4528 | <p>TODO document the reasoning for this</p> |
| 4529 | <p>TODO document whether vice versa should work and why</p> |
| 4530 | {#code_begin|test#} |
| 4531 | test "implicit casting of zero bit types" { |
| 4532 | var x: void = {}; |
| 4533 | var y: *void = x; |
| 4534 | //var z: void = y; // TODO |
| 4535 | } |
| 4536 | {#code_end#} |
| 4388 | 4537 | {#header_close#} |
| 4389 | 4538 | {#header_open|Implicit Cast: undefined#} |
| 4390 | | <p>TODO</p> |
| 4539 | <p>{#link|undefined#} can be cast to any type.</p> |
| 4391 | 4540 | {#header_close#} |
| 4392 | 4541 | {#header_close#} |
| 4393 | 4542 | |