mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
parent
9b99356551
commit
1a94dec50e
@ -4352,42 +4352,191 @@ test "float widening" {
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: Arrays#}
|
||||
<p>TODO: [N]T to []const T</p>
|
||||
<p>TODO: *const [N]T to []const T</p>
|
||||
<p>TODO: [N]T to *const []const T</p>
|
||||
<p>TODO: [N]T to ?[]const T</p>
|
||||
<p>TODO: *[N]T to []T</p>
|
||||
<p>TODO: *[N]T to [*]T</p>
|
||||
<p>TODO: *[N]T to ?[*]T</p>
|
||||
<p>TODO: *T to *[1]T</p>
|
||||
<p>TODO: [N]T to E![]const T</p>
|
||||
{#header_open|Implicit Cast: Arrays and Pointers#}
|
||||
{#code_begin|test#}
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
// This cast exists primarily so that string literals can be
|
||||
// passed to functions that accept const slices. However
|
||||
// it is probably going to be removed from the language when
|
||||
// https://github.com/ziglang/zig/issues/265 is implemented.
|
||||
test "[N]T to []const T" {
|
||||
var x1: []const u8 = "hello";
|
||||
var x2: []const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 };
|
||||
assert(std.mem.eql(u8, x1, x2));
|
||||
|
||||
var y: []const f32 = [2]f32{ 1.2, 3.4 };
|
||||
assert(y[0] == 1.2);
|
||||
}
|
||||
|
||||
// Likewise, it works when the destination type is an error union.
|
||||
test "[N]T to E![]const T" {
|
||||
var x1: anyerror![]const u8 = "hello";
|
||||
var x2: anyerror![]const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 };
|
||||
assert(std.mem.eql(u8, try x1, try x2));
|
||||
|
||||
var y: anyerror![]const f32 = [2]f32{ 1.2, 3.4 };
|
||||
assert((try y)[0] == 1.2);
|
||||
}
|
||||
|
||||
// Likewise, it works when the destination type is an optional.
|
||||
test "[N]T to ?[]const T" {
|
||||
var x1: ?[]const u8 = "hello";
|
||||
var x2: ?[]const u8 = [5]u8{ 'h', 'e', 'l', 'l', 111 };
|
||||
assert(std.mem.eql(u8, x1.?, x2.?));
|
||||
|
||||
var y: ?[]const f32 = [2]f32{ 1.2, 3.4 };
|
||||
assert(y.?[0] == 1.2);
|
||||
}
|
||||
|
||||
// In this cast, the array length becomes the slice length.
|
||||
test "*[N]T to []T" {
|
||||
var buf: [5]u8 = "hello";
|
||||
const x: []u8 = &buf;
|
||||
assert(std.mem.eql(u8, x, "hello"));
|
||||
|
||||
const buf2 = [2]f32{ 1.2, 3.4 };
|
||||
const x2: []const f32 = &buf2;
|
||||
assert(std.mem.eql(f32, x2, [2]f32{ 1.2, 3.4 }));
|
||||
}
|
||||
|
||||
// Single-item pointers to arrays can be implicitly casted to
|
||||
// unknown length pointers.
|
||||
test "*[N]T to [*]T" {
|
||||
var buf: [5]u8 = "hello";
|
||||
const x: [*]u8 = &buf;
|
||||
assert(x[4] == 'o');
|
||||
// x[5] would be an uncaught out of bounds pointer dereference!
|
||||
}
|
||||
|
||||
// Likewise, it works when the destination type is an optional.
|
||||
test "*[N]T to ?[*]T" {
|
||||
var buf: [5]u8 = "hello";
|
||||
const x: ?[*]u8 = &buf;
|
||||
assert(x.?[4] == 'o');
|
||||
}
|
||||
|
||||
// Single-item pointers can be cast to len-1 single-item arrays.
|
||||
test "*T to *[1]T" {
|
||||
var x: i32 = 1234;
|
||||
const y: *[1]i32 = &x;
|
||||
const z: [*]i32 = y;
|
||||
assert(z[0] == 1234);
|
||||
}
|
||||
{#code_end#}
|
||||
{#see_also|C Pointers#}
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: Optionals#}
|
||||
<p>TODO: T to ?T</p>
|
||||
<p>TODO: T to E!?T</p>
|
||||
<p>TODO: null to ?T</p>
|
||||
<p>
|
||||
The payload type of {#link|Optionals#}, as well as {#link|null#}, implicitly cast to the optional type.
|
||||
</p>
|
||||
{#code_begin|test#}
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
test "implicit casting to optionals" {
|
||||
const x: ?i32 = 1234;
|
||||
const y: ?i32 = null;
|
||||
|
||||
assert(x.? == 1234);
|
||||
assert(y == null);
|
||||
}
|
||||
{#code_end#}
|
||||
<p>It works nested inside the {#link|Error Union Type#}, too:</p>
|
||||
{#code_begin|test#}
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
test "implicit casting to optionals wrapped in error union" {
|
||||
const x: anyerror!?i32 = 1234;
|
||||
const y: anyerror!?i32 = null;
|
||||
|
||||
assert((try x).? == 1234);
|
||||
assert((try y) == null);
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: T to E!T#}
|
||||
<p>TODO</p>
|
||||
{#header_open|Implicit Cast: Error Unions#}
|
||||
<p>The the payload type of an {#link|Error Union Type#} as well as the {#link|Error Set Type#}
|
||||
implicitly cast to the error union type:
|
||||
</p>
|
||||
{#code_begin|test#}
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
test "implicit casting to error unions" {
|
||||
const x: anyerror!i32 = 1234;
|
||||
const y: anyerror!i32 = error.Failure;
|
||||
|
||||
assert((try x) == 1234);
|
||||
std.testing.expectError(error.Failure, y);
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: E to E!T#}
|
||||
<p>TODO</p>
|
||||
{#header_open|Implicit Cast: Compile-Time Known Numbers#}
|
||||
<p>When a number is {#link|comptime#}-known to be representable in the destination type,
|
||||
it may be implicitly casted:
|
||||
</p>
|
||||
{#code_begin|test#}
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
test "implicit casting large integer type to smaller one when value is comptime known to fit" {
|
||||
const x: u64 = 255;
|
||||
const y: u8 = x;
|
||||
assert(y == 255);
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: compile-time known numbers#}
|
||||
<p>TODO</p>
|
||||
{#header_open|Implicit Cast: unions and enums#}
|
||||
<p>Tagged unions can be implicitly cast to enums, and enums can be implicitly casted to tagged unions
|
||||
when they are {#link|comptime#}-known to be a field of the union that has only one possible value, such as
|
||||
{#link|void#}:
|
||||
</p>
|
||||
{#code_begin|test#}
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const E = enum {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
};
|
||||
|
||||
const U = union(E) {
|
||||
One: i32,
|
||||
Two: f32,
|
||||
Three,
|
||||
};
|
||||
|
||||
test "implicit casting between unions and enums" {
|
||||
var u = U{ .Two = 12.34 };
|
||||
var e: E = u;
|
||||
assert(e == E.Two);
|
||||
|
||||
const three = E.Three;
|
||||
var another_u: U = three;
|
||||
assert(another_u == E.Three);
|
||||
}
|
||||
{#code_end#}
|
||||
{#see_also|union|enum#}
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: union to enum#}
|
||||
<p>TODO</p>
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: enum to union#}
|
||||
<p>TODO</p>
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: T to *T when @sizeOf(T) == 0#}
|
||||
<p>TODO</p>
|
||||
{#header_open|Implicit Cast: Zero Bit Types#}
|
||||
<p>{#link|Zero Bit Types#} may be implicitly casted to single-item {#link|Pointers#},
|
||||
regardless of const.</p>
|
||||
<p>TODO document the reasoning for this</p>
|
||||
<p>TODO document whether vice versa should work and why</p>
|
||||
{#code_begin|test#}
|
||||
test "implicit casting of zero bit types" {
|
||||
var x: void = {};
|
||||
var y: *void = x;
|
||||
//var z: void = y; // TODO
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
{#header_open|Implicit Cast: undefined#}
|
||||
<p>TODO</p>
|
||||
<p>{#link|undefined#} can be cast to any type.</p>
|
||||
{#header_close#}
|
||||
{#header_close#}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user