mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Some tests are now failing due to debug info changes, some tests now pass due to improved compiler functionality.
1221 lines
24 KiB
Zig
1221 lines
24 KiB
Zig
const builtin = @import("builtin");
|
|
const std = @import("std");
|
|
const expect = std.testing.expect;
|
|
const assert = std.debug.assert;
|
|
const mem = std.mem;
|
|
const Tag = std.meta.Tag;
|
|
|
|
const Number = enum { Zero, One, Two, Three, Four };
|
|
|
|
fn shouldEqual(n: Number, expected: u3) !void {
|
|
try expect(@intFromEnum(n) == expected);
|
|
}
|
|
|
|
test "enum to int" {
|
|
try shouldEqual(Number.Zero, 0);
|
|
try shouldEqual(Number.One, 1);
|
|
try shouldEqual(Number.Two, 2);
|
|
try shouldEqual(Number.Three, 3);
|
|
try shouldEqual(Number.Four, 4);
|
|
}
|
|
|
|
fn testIntToEnumEval(x: i32) !void {
|
|
try expect(@as(IntToEnumNumber, @enumFromInt(x)) == IntToEnumNumber.Three);
|
|
}
|
|
const IntToEnumNumber = enum { Zero, One, Two, Three, Four };
|
|
|
|
test "int to enum" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testIntToEnumEval(3);
|
|
}
|
|
|
|
const ValueCount1 = enum {
|
|
I0,
|
|
};
|
|
const ValueCount2 = enum {
|
|
I0,
|
|
I1,
|
|
};
|
|
const ValueCount256 = enum {
|
|
I0,
|
|
I1,
|
|
I2,
|
|
I3,
|
|
I4,
|
|
I5,
|
|
I6,
|
|
I7,
|
|
I8,
|
|
I9,
|
|
I10,
|
|
I11,
|
|
I12,
|
|
I13,
|
|
I14,
|
|
I15,
|
|
I16,
|
|
I17,
|
|
I18,
|
|
I19,
|
|
I20,
|
|
I21,
|
|
I22,
|
|
I23,
|
|
I24,
|
|
I25,
|
|
I26,
|
|
I27,
|
|
I28,
|
|
I29,
|
|
I30,
|
|
I31,
|
|
I32,
|
|
I33,
|
|
I34,
|
|
I35,
|
|
I36,
|
|
I37,
|
|
I38,
|
|
I39,
|
|
I40,
|
|
I41,
|
|
I42,
|
|
I43,
|
|
I44,
|
|
I45,
|
|
I46,
|
|
I47,
|
|
I48,
|
|
I49,
|
|
I50,
|
|
I51,
|
|
I52,
|
|
I53,
|
|
I54,
|
|
I55,
|
|
I56,
|
|
I57,
|
|
I58,
|
|
I59,
|
|
I60,
|
|
I61,
|
|
I62,
|
|
I63,
|
|
I64,
|
|
I65,
|
|
I66,
|
|
I67,
|
|
I68,
|
|
I69,
|
|
I70,
|
|
I71,
|
|
I72,
|
|
I73,
|
|
I74,
|
|
I75,
|
|
I76,
|
|
I77,
|
|
I78,
|
|
I79,
|
|
I80,
|
|
I81,
|
|
I82,
|
|
I83,
|
|
I84,
|
|
I85,
|
|
I86,
|
|
I87,
|
|
I88,
|
|
I89,
|
|
I90,
|
|
I91,
|
|
I92,
|
|
I93,
|
|
I94,
|
|
I95,
|
|
I96,
|
|
I97,
|
|
I98,
|
|
I99,
|
|
I100,
|
|
I101,
|
|
I102,
|
|
I103,
|
|
I104,
|
|
I105,
|
|
I106,
|
|
I107,
|
|
I108,
|
|
I109,
|
|
I110,
|
|
I111,
|
|
I112,
|
|
I113,
|
|
I114,
|
|
I115,
|
|
I116,
|
|
I117,
|
|
I118,
|
|
I119,
|
|
I120,
|
|
I121,
|
|
I122,
|
|
I123,
|
|
I124,
|
|
I125,
|
|
I126,
|
|
I127,
|
|
I128,
|
|
I129,
|
|
I130,
|
|
I131,
|
|
I132,
|
|
I133,
|
|
I134,
|
|
I135,
|
|
I136,
|
|
I137,
|
|
I138,
|
|
I139,
|
|
I140,
|
|
I141,
|
|
I142,
|
|
I143,
|
|
I144,
|
|
I145,
|
|
I146,
|
|
I147,
|
|
I148,
|
|
I149,
|
|
I150,
|
|
I151,
|
|
I152,
|
|
I153,
|
|
I154,
|
|
I155,
|
|
I156,
|
|
I157,
|
|
I158,
|
|
I159,
|
|
I160,
|
|
I161,
|
|
I162,
|
|
I163,
|
|
I164,
|
|
I165,
|
|
I166,
|
|
I167,
|
|
I168,
|
|
I169,
|
|
I170,
|
|
I171,
|
|
I172,
|
|
I173,
|
|
I174,
|
|
I175,
|
|
I176,
|
|
I177,
|
|
I178,
|
|
I179,
|
|
I180,
|
|
I181,
|
|
I182,
|
|
I183,
|
|
I184,
|
|
I185,
|
|
I186,
|
|
I187,
|
|
I188,
|
|
I189,
|
|
I190,
|
|
I191,
|
|
I192,
|
|
I193,
|
|
I194,
|
|
I195,
|
|
I196,
|
|
I197,
|
|
I198,
|
|
I199,
|
|
I200,
|
|
I201,
|
|
I202,
|
|
I203,
|
|
I204,
|
|
I205,
|
|
I206,
|
|
I207,
|
|
I208,
|
|
I209,
|
|
I210,
|
|
I211,
|
|
I212,
|
|
I213,
|
|
I214,
|
|
I215,
|
|
I216,
|
|
I217,
|
|
I218,
|
|
I219,
|
|
I220,
|
|
I221,
|
|
I222,
|
|
I223,
|
|
I224,
|
|
I225,
|
|
I226,
|
|
I227,
|
|
I228,
|
|
I229,
|
|
I230,
|
|
I231,
|
|
I232,
|
|
I233,
|
|
I234,
|
|
I235,
|
|
I236,
|
|
I237,
|
|
I238,
|
|
I239,
|
|
I240,
|
|
I241,
|
|
I242,
|
|
I243,
|
|
I244,
|
|
I245,
|
|
I246,
|
|
I247,
|
|
I248,
|
|
I249,
|
|
I250,
|
|
I251,
|
|
I252,
|
|
I253,
|
|
I254,
|
|
I255,
|
|
};
|
|
const ValueCount257 = enum {
|
|
I0,
|
|
I1,
|
|
I2,
|
|
I3,
|
|
I4,
|
|
I5,
|
|
I6,
|
|
I7,
|
|
I8,
|
|
I9,
|
|
I10,
|
|
I11,
|
|
I12,
|
|
I13,
|
|
I14,
|
|
I15,
|
|
I16,
|
|
I17,
|
|
I18,
|
|
I19,
|
|
I20,
|
|
I21,
|
|
I22,
|
|
I23,
|
|
I24,
|
|
I25,
|
|
I26,
|
|
I27,
|
|
I28,
|
|
I29,
|
|
I30,
|
|
I31,
|
|
I32,
|
|
I33,
|
|
I34,
|
|
I35,
|
|
I36,
|
|
I37,
|
|
I38,
|
|
I39,
|
|
I40,
|
|
I41,
|
|
I42,
|
|
I43,
|
|
I44,
|
|
I45,
|
|
I46,
|
|
I47,
|
|
I48,
|
|
I49,
|
|
I50,
|
|
I51,
|
|
I52,
|
|
I53,
|
|
I54,
|
|
I55,
|
|
I56,
|
|
I57,
|
|
I58,
|
|
I59,
|
|
I60,
|
|
I61,
|
|
I62,
|
|
I63,
|
|
I64,
|
|
I65,
|
|
I66,
|
|
I67,
|
|
I68,
|
|
I69,
|
|
I70,
|
|
I71,
|
|
I72,
|
|
I73,
|
|
I74,
|
|
I75,
|
|
I76,
|
|
I77,
|
|
I78,
|
|
I79,
|
|
I80,
|
|
I81,
|
|
I82,
|
|
I83,
|
|
I84,
|
|
I85,
|
|
I86,
|
|
I87,
|
|
I88,
|
|
I89,
|
|
I90,
|
|
I91,
|
|
I92,
|
|
I93,
|
|
I94,
|
|
I95,
|
|
I96,
|
|
I97,
|
|
I98,
|
|
I99,
|
|
I100,
|
|
I101,
|
|
I102,
|
|
I103,
|
|
I104,
|
|
I105,
|
|
I106,
|
|
I107,
|
|
I108,
|
|
I109,
|
|
I110,
|
|
I111,
|
|
I112,
|
|
I113,
|
|
I114,
|
|
I115,
|
|
I116,
|
|
I117,
|
|
I118,
|
|
I119,
|
|
I120,
|
|
I121,
|
|
I122,
|
|
I123,
|
|
I124,
|
|
I125,
|
|
I126,
|
|
I127,
|
|
I128,
|
|
I129,
|
|
I130,
|
|
I131,
|
|
I132,
|
|
I133,
|
|
I134,
|
|
I135,
|
|
I136,
|
|
I137,
|
|
I138,
|
|
I139,
|
|
I140,
|
|
I141,
|
|
I142,
|
|
I143,
|
|
I144,
|
|
I145,
|
|
I146,
|
|
I147,
|
|
I148,
|
|
I149,
|
|
I150,
|
|
I151,
|
|
I152,
|
|
I153,
|
|
I154,
|
|
I155,
|
|
I156,
|
|
I157,
|
|
I158,
|
|
I159,
|
|
I160,
|
|
I161,
|
|
I162,
|
|
I163,
|
|
I164,
|
|
I165,
|
|
I166,
|
|
I167,
|
|
I168,
|
|
I169,
|
|
I170,
|
|
I171,
|
|
I172,
|
|
I173,
|
|
I174,
|
|
I175,
|
|
I176,
|
|
I177,
|
|
I178,
|
|
I179,
|
|
I180,
|
|
I181,
|
|
I182,
|
|
I183,
|
|
I184,
|
|
I185,
|
|
I186,
|
|
I187,
|
|
I188,
|
|
I189,
|
|
I190,
|
|
I191,
|
|
I192,
|
|
I193,
|
|
I194,
|
|
I195,
|
|
I196,
|
|
I197,
|
|
I198,
|
|
I199,
|
|
I200,
|
|
I201,
|
|
I202,
|
|
I203,
|
|
I204,
|
|
I205,
|
|
I206,
|
|
I207,
|
|
I208,
|
|
I209,
|
|
I210,
|
|
I211,
|
|
I212,
|
|
I213,
|
|
I214,
|
|
I215,
|
|
I216,
|
|
I217,
|
|
I218,
|
|
I219,
|
|
I220,
|
|
I221,
|
|
I222,
|
|
I223,
|
|
I224,
|
|
I225,
|
|
I226,
|
|
I227,
|
|
I228,
|
|
I229,
|
|
I230,
|
|
I231,
|
|
I232,
|
|
I233,
|
|
I234,
|
|
I235,
|
|
I236,
|
|
I237,
|
|
I238,
|
|
I239,
|
|
I240,
|
|
I241,
|
|
I242,
|
|
I243,
|
|
I244,
|
|
I245,
|
|
I246,
|
|
I247,
|
|
I248,
|
|
I249,
|
|
I250,
|
|
I251,
|
|
I252,
|
|
I253,
|
|
I254,
|
|
I255,
|
|
I256,
|
|
};
|
|
|
|
test "enum sizes" {
|
|
comptime {
|
|
try expect(@sizeOf(ValueCount1) == 0);
|
|
try expect(@sizeOf(ValueCount2) == 1);
|
|
try expect(@sizeOf(ValueCount256) == 1);
|
|
try expect(@sizeOf(ValueCount257) == 2);
|
|
}
|
|
}
|
|
|
|
test "enum literal equality" {
|
|
const x = .hi;
|
|
const y = .ok;
|
|
const z = .hi;
|
|
|
|
try expect(x != y);
|
|
try expect(x == z);
|
|
}
|
|
|
|
test "enum literal cast to enum" {
|
|
const Color = enum { Auto, Off, On };
|
|
|
|
var color1: Color = .Auto;
|
|
var color2 = Color.Auto;
|
|
try expect(color1 == color2);
|
|
}
|
|
|
|
test "peer type resolution with enum literal" {
|
|
const Items = enum { one, two };
|
|
|
|
try expect(Items.two == .two);
|
|
try expect(.two == Items.two);
|
|
}
|
|
|
|
const MultipleChoice = enum(u32) {
|
|
A = 20,
|
|
B = 40,
|
|
C = 60,
|
|
D = 1000,
|
|
};
|
|
|
|
fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
|
|
try expect(@intFromEnum(x) == 60);
|
|
try expect(1234 == switch (x) {
|
|
MultipleChoice.A => 1,
|
|
MultipleChoice.B => 2,
|
|
MultipleChoice.C => @as(u32, 1234),
|
|
MultipleChoice.D => 4,
|
|
});
|
|
}
|
|
|
|
test "enum with specified tag values" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testEnumWithSpecifiedTagValues(MultipleChoice.C);
|
|
try comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
|
|
}
|
|
|
|
test "non-exhaustive enum" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const E = enum(u8) { a, b, _ };
|
|
|
|
fn doTheTest(y: u8) !void {
|
|
var e: E = .b;
|
|
try expect(switch (e) {
|
|
.a => false,
|
|
.b => true,
|
|
_ => false,
|
|
});
|
|
e = @as(E, @enumFromInt(12));
|
|
try expect(switch (e) {
|
|
.a => false,
|
|
.b => false,
|
|
_ => true,
|
|
});
|
|
|
|
try expect(switch (e) {
|
|
.a => false,
|
|
.b => false,
|
|
else => true,
|
|
});
|
|
e = .b;
|
|
try expect(switch (e) {
|
|
.a => false,
|
|
else => true,
|
|
});
|
|
|
|
try expect(@typeInfo(E).Enum.fields.len == 2);
|
|
e = @as(E, @enumFromInt(12));
|
|
try expect(@intFromEnum(e) == 12);
|
|
e = @as(E, @enumFromInt(y));
|
|
try expect(@intFromEnum(e) == 52);
|
|
try expect(@typeInfo(E).Enum.is_exhaustive == false);
|
|
}
|
|
};
|
|
try S.doTheTest(52);
|
|
try comptime S.doTheTest(52);
|
|
}
|
|
|
|
test "empty non-exhaustive enum" {
|
|
const S = struct {
|
|
const E = enum(u8) { _ };
|
|
|
|
fn doTheTest(y: u8) !void {
|
|
var e = @as(E, @enumFromInt(y));
|
|
try expect(switch (e) {
|
|
_ => true,
|
|
});
|
|
try expect(@intFromEnum(e) == y);
|
|
|
|
try expect(@typeInfo(E).Enum.fields.len == 0);
|
|
try expect(@typeInfo(E).Enum.is_exhaustive == false);
|
|
}
|
|
};
|
|
try S.doTheTest(42);
|
|
try comptime S.doTheTest(42);
|
|
}
|
|
|
|
test "single field non-exhaustive enum" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const E = enum(u8) { a, _ };
|
|
fn doTheTest(y: u8) !void {
|
|
var e: E = .a;
|
|
try expect(switch (e) {
|
|
.a => true,
|
|
_ => false,
|
|
});
|
|
e = @as(E, @enumFromInt(12));
|
|
try expect(switch (e) {
|
|
.a => false,
|
|
_ => true,
|
|
});
|
|
|
|
try expect(switch (e) {
|
|
.a => false,
|
|
else => true,
|
|
});
|
|
e = .a;
|
|
try expect(switch (e) {
|
|
.a => true,
|
|
else => false,
|
|
});
|
|
|
|
try expect(@intFromEnum(@as(E, @enumFromInt(y))) == y);
|
|
try expect(@typeInfo(E).Enum.fields.len == 1);
|
|
try expect(@typeInfo(E).Enum.is_exhaustive == false);
|
|
}
|
|
};
|
|
try S.doTheTest(23);
|
|
try comptime S.doTheTest(23);
|
|
}
|
|
|
|
const EnumWithTagValues = enum(u4) {
|
|
A = 1 << 0,
|
|
B = 1 << 1,
|
|
C = 1 << 2,
|
|
D = 1 << 3,
|
|
};
|
|
test "enum with tag values don't require parens" {
|
|
try expect(@intFromEnum(EnumWithTagValues.C) == 0b0100);
|
|
}
|
|
|
|
const MultipleChoice2 = enum(u32) {
|
|
Unspecified1,
|
|
A = 20,
|
|
Unspecified2,
|
|
B = 40,
|
|
Unspecified3,
|
|
C = 60,
|
|
Unspecified4,
|
|
D = 1000,
|
|
Unspecified5,
|
|
};
|
|
|
|
test "cast integer literal to enum" {
|
|
try expect(@as(MultipleChoice2, @enumFromInt(0)) == MultipleChoice2.Unspecified1);
|
|
try expect(@as(MultipleChoice2, @enumFromInt(40)) == MultipleChoice2.B);
|
|
}
|
|
|
|
test "enum with specified and unspecified tag values" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
|
|
try comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
|
|
}
|
|
|
|
fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
|
|
try expect(@intFromEnum(x) == 1000);
|
|
try expect(1234 == switch (x) {
|
|
MultipleChoice2.A => 1,
|
|
MultipleChoice2.B => 2,
|
|
MultipleChoice2.C => 3,
|
|
MultipleChoice2.D => @as(u32, 1234),
|
|
MultipleChoice2.Unspecified1 => 5,
|
|
MultipleChoice2.Unspecified2 => 6,
|
|
MultipleChoice2.Unspecified3 => 7,
|
|
MultipleChoice2.Unspecified4 => 8,
|
|
MultipleChoice2.Unspecified5 => 9,
|
|
});
|
|
}
|
|
|
|
const Small2 = enum(u2) { One, Two };
|
|
const Small = enum(u2) { One, Two, Three, Four };
|
|
|
|
test "set enum tag type" {
|
|
{
|
|
var x = Small.One;
|
|
x = Small.Two;
|
|
try comptime expect(Tag(Small) == u2);
|
|
}
|
|
{
|
|
var x = Small2.One;
|
|
x = Small2.Two;
|
|
try comptime expect(Tag(Small2) == u2);
|
|
}
|
|
}
|
|
|
|
test "casting enum to its tag type" {
|
|
try testCastEnumTag(Small2.Two);
|
|
try comptime testCastEnumTag(Small2.Two);
|
|
}
|
|
|
|
fn testCastEnumTag(value: Small2) !void {
|
|
try expect(@intFromEnum(value) == 1);
|
|
}
|
|
|
|
test "enum with 1 field but explicit tag type should still have the tag type" {
|
|
const Enum = enum(u8) {
|
|
B = 2,
|
|
};
|
|
try comptime expect(@sizeOf(Enum) == @sizeOf(u8));
|
|
}
|
|
|
|
test "signed integer as enum tag" {
|
|
const SignedEnum = enum(i2) {
|
|
A0 = -1,
|
|
A1 = 0,
|
|
A2 = 1,
|
|
};
|
|
|
|
try expect(@intFromEnum(SignedEnum.A0) == -1);
|
|
try expect(@intFromEnum(SignedEnum.A1) == 0);
|
|
try expect(@intFromEnum(SignedEnum.A2) == 1);
|
|
}
|
|
|
|
test "enum with one member and custom tag type" {
|
|
const E = enum(u2) {
|
|
One,
|
|
};
|
|
try expect(@intFromEnum(E.One) == 0);
|
|
const E2 = enum(u2) {
|
|
One = 2,
|
|
};
|
|
try expect(@intFromEnum(E2.One) == 2);
|
|
}
|
|
|
|
test "enum with one member and u1 tag type @intFromEnum" {
|
|
const Enum = enum(u1) {
|
|
Test,
|
|
};
|
|
try expect(@intFromEnum(Enum.Test) == 0);
|
|
}
|
|
|
|
test "enum with comptime_int tag type" {
|
|
const Enum = enum(comptime_int) {
|
|
One = 3,
|
|
Two = 2,
|
|
Three = 1,
|
|
};
|
|
try comptime expect(Tag(Enum) == comptime_int);
|
|
}
|
|
|
|
test "enum with one member default to u0 tag type" {
|
|
const E0 = enum { X };
|
|
try comptime expect(Tag(E0) == u0);
|
|
}
|
|
|
|
const EnumWithOneMember = enum { Eof };
|
|
|
|
fn doALoopThing(id: EnumWithOneMember) void {
|
|
while (true) {
|
|
if (id == EnumWithOneMember.Eof) {
|
|
break;
|
|
}
|
|
@compileError("above if condition should be comptime");
|
|
}
|
|
}
|
|
|
|
test "comparison operator on enum with one member is comptime-known" {
|
|
doALoopThing(EnumWithOneMember.Eof);
|
|
}
|
|
|
|
const State = enum { Start };
|
|
test "switch on enum with one member is comptime-known" {
|
|
var state = State.Start;
|
|
switch (state) {
|
|
State.Start => return,
|
|
}
|
|
@compileError("analysis should not reach here");
|
|
}
|
|
|
|
test "method call on an enum" {
|
|
const S = struct {
|
|
const E = enum {
|
|
one,
|
|
two,
|
|
|
|
fn method(self: *E) bool {
|
|
return self.* == .two;
|
|
}
|
|
|
|
fn generic_method(self: *E, foo: anytype) bool {
|
|
return self.* == .two and foo == bool;
|
|
}
|
|
};
|
|
fn doTheTest() !void {
|
|
var e = E.two;
|
|
try expect(e.method());
|
|
try expect(e.generic_method(bool));
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "enum value allocation" {
|
|
const LargeEnum = enum(u32) {
|
|
A0 = 0x80000000,
|
|
A1,
|
|
A2,
|
|
};
|
|
|
|
try expect(@intFromEnum(LargeEnum.A0) == 0x80000000);
|
|
try expect(@intFromEnum(LargeEnum.A1) == 0x80000001);
|
|
try expect(@intFromEnum(LargeEnum.A2) == 0x80000002);
|
|
}
|
|
|
|
test "enum literal casting to tagged union" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const Arch = union(enum) {
|
|
x86_64,
|
|
arm: Arm32,
|
|
|
|
const Arm32 = enum {
|
|
v8_5a,
|
|
v8_4a,
|
|
};
|
|
};
|
|
|
|
var t = true;
|
|
var x: Arch = .x86_64;
|
|
var y = if (t) x else .x86_64;
|
|
switch (y) {
|
|
.x86_64 => {},
|
|
else => @panic("fail"),
|
|
}
|
|
}
|
|
|
|
const Bar = enum { A, B, C, D };
|
|
|
|
test "enum literal casting to error union with payload enum" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
var bar: error{B}!Bar = undefined;
|
|
bar = .B; // should never cast to the error set
|
|
|
|
try expect((try bar) == Bar.B);
|
|
}
|
|
|
|
test "constant enum initialization with differing sizes" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try test3_1(test3_foo);
|
|
try test3_2(test3_bar);
|
|
}
|
|
const Test3Foo = union(enum) {
|
|
One: void,
|
|
Two: f32,
|
|
Three: Test3Point,
|
|
};
|
|
const Test3Point = struct {
|
|
x: i32,
|
|
y: i32,
|
|
};
|
|
const test3_foo = Test3Foo{
|
|
.Three = Test3Point{
|
|
.x = 3,
|
|
.y = 4,
|
|
},
|
|
};
|
|
const test3_bar = Test3Foo{ .Two = 13 };
|
|
fn test3_1(f: Test3Foo) !void {
|
|
switch (f) {
|
|
Test3Foo.Three => |pt| {
|
|
try expect(pt.x == 3);
|
|
try expect(pt.y == 4);
|
|
},
|
|
else => unreachable,
|
|
}
|
|
}
|
|
fn test3_2(f: Test3Foo) !void {
|
|
switch (f) {
|
|
Test3Foo.Two => |x| {
|
|
try expect(x == 13);
|
|
},
|
|
else => unreachable,
|
|
}
|
|
}
|
|
|
|
test "@tagName" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
|
try comptime expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
|
}
|
|
|
|
fn testEnumTagNameBare(n: anytype) []const u8 {
|
|
return @tagName(n);
|
|
}
|
|
|
|
const BareNumber = enum { One, Two, Three };
|
|
|
|
test "@tagName non-exhaustive enum" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
|
|
try comptime expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
|
|
}
|
|
const NonExhaustive = enum(u8) { A, B, _ };
|
|
|
|
test "@tagName is null-terminated" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
fn doTheTest(n: BareNumber) !void {
|
|
try expect(@tagName(n)[3] == 0);
|
|
}
|
|
};
|
|
try S.doTheTest(.Two);
|
|
try comptime S.doTheTest(.Two);
|
|
}
|
|
|
|
test "tag name with assigned enum values" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const LocalFoo = enum(u8) {
|
|
A = 1,
|
|
B = 0,
|
|
};
|
|
var b = LocalFoo.B;
|
|
try expect(mem.eql(u8, @tagName(b), "B"));
|
|
}
|
|
|
|
test "@tagName on enum literals" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
|
|
try comptime expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
|
|
}
|
|
|
|
test "tag name with signed enum values" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const LocalFoo = enum(isize) {
|
|
alfa = 62,
|
|
bravo = 63,
|
|
charlie = 64,
|
|
delta = 65,
|
|
};
|
|
var b = LocalFoo.bravo;
|
|
try expect(mem.eql(u8, @tagName(b), "bravo"));
|
|
}
|
|
|
|
test "enum literal casting to optional" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
var bar: ?Bar = undefined;
|
|
bar = .B;
|
|
|
|
try expect(bar.? == Bar.B);
|
|
}
|
|
|
|
const A = enum(u3) { One, Two, Three, Four, One2, Two2, Three2, Four2 };
|
|
const B = enum(u3) { One3, Two3, Three3, Four3, One23, Two23, Three23, Four23 };
|
|
const C = enum(u2) { One4, Two4, Three4, Four4 };
|
|
|
|
const BitFieldOfEnums = packed struct {
|
|
a: A,
|
|
b: B,
|
|
c: C,
|
|
};
|
|
|
|
const bit_field_1 = BitFieldOfEnums{
|
|
.a = A.Two,
|
|
.b = B.Three3,
|
|
.c = C.Four4,
|
|
};
|
|
|
|
test "bit field access with enum fields" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
var data = bit_field_1;
|
|
try expect(getA(&data) == A.Two);
|
|
try expect(getB(&data) == B.Three3);
|
|
try expect(getC(&data) == C.Four4);
|
|
try comptime expect(@sizeOf(BitFieldOfEnums) == 1);
|
|
|
|
data.b = B.Four3;
|
|
try expect(data.b == B.Four3);
|
|
|
|
data.a = A.Three;
|
|
try expect(data.a == A.Three);
|
|
try expect(data.b == B.Four3);
|
|
}
|
|
|
|
fn getA(data: *const BitFieldOfEnums) A {
|
|
return data.a;
|
|
}
|
|
|
|
fn getB(data: *const BitFieldOfEnums) B {
|
|
return data.b;
|
|
}
|
|
|
|
fn getC(data: *const BitFieldOfEnums) C {
|
|
return data.c;
|
|
}
|
|
|
|
test "enum literal in array literal" {
|
|
const Items = enum { one, two };
|
|
const array = [_]Items{ .one, .two };
|
|
|
|
try expect(array[0] == .one);
|
|
try expect(array[1] == .two);
|
|
}
|
|
|
|
test "tag name functions are unique" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
{
|
|
const E = enum { a, b };
|
|
var b = E.a;
|
|
var a = @tagName(b);
|
|
_ = a;
|
|
}
|
|
{
|
|
const E = enum { a, b, c, d, e, f };
|
|
var b = E.a;
|
|
var a = @tagName(b);
|
|
_ = a;
|
|
}
|
|
}
|
|
|
|
test "size of enum with only one tag which has explicit integer tag type" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const E = enum(u8) { nope = 10 };
|
|
const S0 = struct { e: E };
|
|
const S1 = extern struct { e: E };
|
|
//const U = union(E) { nope: void };
|
|
comptime assert(@sizeOf(E) == 1);
|
|
comptime assert(@sizeOf(S0) == 1);
|
|
comptime assert(@sizeOf(S1) == 1);
|
|
//comptime assert(@sizeOf(U) == 1);
|
|
|
|
var s1: S1 = undefined;
|
|
s1.e = .nope;
|
|
try expect(s1.e == .nope);
|
|
const ptr = @as(*u8, @ptrCast(&s1));
|
|
try expect(ptr.* == 10);
|
|
|
|
var s0: S0 = undefined;
|
|
s0.e = .nope;
|
|
try expect(s0.e == .nope);
|
|
}
|
|
|
|
test "switch on an extern enum with negative value" {
|
|
const Foo = enum(c_int) {
|
|
Bar = -1,
|
|
};
|
|
|
|
const v = Foo.Bar;
|
|
|
|
switch (v) {
|
|
Foo.Bar => return,
|
|
}
|
|
}
|
|
|
|
test "Non-exhaustive enum with nonstandard int size behaves correctly" {
|
|
const E = enum(u15) { _ };
|
|
try expect(@sizeOf(E) == @sizeOf(u15));
|
|
}
|
|
|
|
test "runtime int to enum with one possible value" {
|
|
const E = enum { one };
|
|
var runtime: usize = 0;
|
|
if (@as(E, @enumFromInt(runtime)) != .one) {
|
|
@compileError("test failed");
|
|
}
|
|
}
|
|
|
|
test "enum tag from a local variable" {
|
|
const S = struct {
|
|
fn Int(comptime Inner: type) type {
|
|
return enum(Inner) { _ };
|
|
}
|
|
};
|
|
const i = @as(S.Int(u32), @enumFromInt(0));
|
|
try std.testing.expect(@intFromEnum(i) == 0);
|
|
}
|
|
|
|
test "auto-numbered enum with signed tag type" {
|
|
const E = enum(i32) { a, b };
|
|
|
|
try std.testing.expectEqual(@as(i32, 0), @intFromEnum(E.a));
|
|
try std.testing.expectEqual(@as(i32, 1), @intFromEnum(E.b));
|
|
try std.testing.expectEqual(E.a, @as(E, @enumFromInt(0)));
|
|
try std.testing.expectEqual(E.b, @as(E, @enumFromInt(1)));
|
|
try std.testing.expectEqual(E.a, @as(E, @enumFromInt(@as(i32, 0))));
|
|
try std.testing.expectEqual(E.b, @as(E, @enumFromInt(@as(i32, 1))));
|
|
try std.testing.expectEqual(E.a, @as(E, @enumFromInt(@as(u32, 0))));
|
|
try std.testing.expectEqual(E.b, @as(E, @enumFromInt(@as(u32, 1))));
|
|
try std.testing.expectEqualStrings("a", @tagName(E.a));
|
|
try std.testing.expectEqualStrings("b", @tagName(E.b));
|
|
}
|