配列を、構造体のように初期化しようとしています。配列は配列の値で初期化して ください。
次の例では、array1
と array2
はどちらも u8
の配列ですが、 array2
は
構造体の値 { .x = 42, }
で初期化されています。
pub fn main() anyerror!void {
const array1 = [_]u8{ 0, 1, 2, }; // 正しい配列初期化
const array2 = [_]u8{ .x = 42, }; // エラー
}
コンパイルは失敗します。
$ zen run src/main.zen
src/main.zen:3:20: エラー[E09000]: 配列を構造体の構文で初期化しています。
const array2 = [_]u8{ .x = 42, }; // エラー
~
配列またはスライスを、構造体の値で初期化しようとしています。
次の例では、y
は [4]u8
、つまり 4 要素の u8
配列です。
また z
は []u8
、つまり u8
配列へのスライスです。
両者とも誤って構造体の値 { .len = 42, }
で初期化されています。
fn error1() void {
var x = ([4]u8){ 0, 1, 2, 3, }; // 正しい配列初期化
var y = ([4]u8){ .len = 42, }; // エラー
}
fn error2() void {
var z = ([]u8){ .len = 42, }; // エラー
}
pub fn main() anyerror!void {
error1();
error2();
}
コンパイルは失敗します。
$ zen run src/main.zen
src/main.zen:3:22: エラー[E09001]: 「[4]u8」型は構造体形式の初期化をサポートしていません。
var y = ([4]u8){ .len = 42, }; // エラー
~
src/main.zen:7:19: エラー[E09001]: 「[]u8」型は構造体形式の初期化をサポートしていません。
var z = ([]u8){ .len = 42, }; // エラー
~
配列形式の初期化が、配列でない型に使われています。
正しい初期化の例を以下に示します。
a
は配列でない変数の初期化の、b
は配列型変数の初期化の例です。
pub fn main() anyerror!void {
var a: u32 = 42; // ok
var b = [4]u32{ 0, 1, 2, 3, }; // ok
var c = u32{}; // error
}
ポインタ型でない仮引数に noalias
修飾子が使われています。
noalias
修飾子は、修飾されたポインタが指すメモリ領域へのアクセスに
ある制限を加えるものです。従ってポインタ型以外の仮引数に使っても
効果がありません。
fn func1(noalias x: *i32) void {
}
fn func2(noalias x: i32) void { // エラー
}
pub fn main() anyerror!void {
var x: i32 = 42;
func1(&x);
func2(x);
}
コンパイルは失敗します:
$ zen run src/main.zen
src/main.zen:4:10: エラー[E09003]: ポインタでない引数には「noalias」は使えません。
fn func2(noalias x: i32) void { // エラー
~
変数が const
であることが期待されている箇所で、そうなっていません。
例えば、Zen では型はコンパイル時に計算可能な定数 (const) である必要があります。
以下のコードでは、MyTypeConst
は型 (この場合は u8
) を値として持つ
const 変数であり、別の変数 foo
の型として使うことができます。
一方、MyTypeVar
も型を値として持つ変数なので、const である事が
期待されますが、そうなっていません。このためコンパイルエラーとなります。
const MyTypeConst: type = u8;
var MyTypeVar: type = u8; // エラー
pub fn main() anyerror!void {
var foo: MyTypeConst = 42; // ok
var bar: MyTypeVar = 42;
}
インスタンスを作成できない型の変数を定義しようとしています。
次のコードでは、O
はサイズが不明な型です。main
の中で foo
を
定義しようとしていますが、サイズが不明なのでメモリを割り当てることが
できません。このためコンパイルエラーとなります。
const O = @OpaqueType();
pub fn main() anyerror!void {
var foo: O = undefined; // error
}
メモリ領域を割り当てる時に、そのサイズが未確定となっています。
次のコードでは、組込み関数 @OpaqueType
はサイズが 1 以上の
新たな型を返しますが、その具体的なサイズは未確定なままとなっています。
このため、構造体の o
フィールドにメモリを割り当てることができません。
const O = @OpaqueType();
const MyStruct = struct {
o: O, // error
};
それ自身に依存するような型を定義しようとしています。
const A = struct { a: A, }; // エラー
依存関係が込み入っている場合もあります。次のコードでは、X
は間接的に
X
自身に依存しています。
const X = struct { y: Y, }; // エラー: X は間接的に X 自身に依存している
const Y = struct { z: Z, }; // エラー
const Z = struct { x: X, }; // エラー
packed
や extern
指定のあるコンテナー (struct や union) には、
それに含まれるフィールドやヴァリアントについて、
通常のコンテナーにはない制限があります。
制限に触れた点があれば解決してください。
const MyStruct1 = packed struct {
foo: anyerror, // error
};
const MyStruct2 = packed struct {
foo: [1]I32AndU32, // error
};
const MyStruct3 = extern struct {
foo: ?*void, // error
};
const MyStruct4 = packed union {
foo: U32AndF32, // error
bar: bool,
};
const I32AndU32 = struct {
x: i32,
y: u32,
};
const U32AndF32 = struct {
x: u32,
y: f32,
};
Zen では、インタフェースはジェネリック関数を含んではいけません。 インタフェースがジェネリック関数を含まない形へ、 ソースコードを修正してください。
ジェネリック関数とは、型を引数として受け取る関数のことです。
型は anytype
または comptime type
として受け取ります。
const MyInterface1 = interface {
fn foo(a: anytype) @TypeOf(a); // error
};
const MyInterface2 = interface {
fn foo(comptime T: type) T; // error
};
extern enum
では使えないタグ型を extern enum(タグ型)
のように使っています。
extern enum
は C ABI と互換性があるため、
タグ型は C と Zen の両方で使える型である必要があります。
次の例では、u9
という型は C にないため、
extern enum
のタグ型として使うとエラーになります。
const RGB = extern enum(u8) { // ok
Red,
Green,
Blue,
};
const CMY = extern enum(u9) { // error
Cyan,
Magenta,
Yellow,
};
comptime
で宣言されるべき仮引数が、そうなっていません。
次の例では、どちらの関数でも仮引数 T
は型を受け取ります。
Zen では型を受け取る仮引数は comptime
で宣言する必要があるので、
後者の関数はエラーとなります。
fn the_answer(comptime T: type) T { // ok
return 42;
}
fn the_rating(T: type) T { // error
return 158.3;
}
組込み関数 @byteSwap
の第1引数は、ビット幅が 8 の倍数であるような
整数型である必要があります。
次の例では、最初の @byteSwap
は正しく動作します。
16 は 8 の倍数であり、0xFF00 は u16
型の値であるからです。
2 番目の @byteSwap
は u15
を受け取っていますが、
15 は 8 の倍数ではないのでエラーとなります。
pub fn main() anyerror!void {
assert(@byteSwap(u16, 0xFF00) == 0x00FF);
const foo: u15 = 0x7F00;
const bar = @byteSwap(u15, foo); // error
}
このエラーコードが存在しますが説明がございません。
このエラーコードが存在しますが説明がございません。
整数型の値のビット幅が大きすぎます。
次の例では、'atomic' 組込み関数は通常はターゲット CPU のアトミック操作命令を 利用するため、扱えるデータのサイズに制限があります。 64 ビット CPU では 64 ビットや 128 ビットのデータをアトミックに操作できる 場合が多いですが、32768 ビット (4096 バイト) は大きすぎて扱えません。
pub fn main() anyerror!void {
var foo: u64 = 42;
_ = @atomicStore(u64, &mut foo, 101, .SeqCst); // ok
var bar: u32768 = 42;
_ = @atomicStore(u32768, &mut bar, 101, .SeqCst); // error
}
このエラーコードが存在しますが説明がございません。
このエラーコードが存在しますが説明がございません。
C ポインタが、オペーク型 (内容の不明な型) を指しています。
次の例では、opaque_pointer
は C 言語の void ポインタです。
これが指すデータが何なのかこの時点では分からない
(char
かもしれないし uint64_t
かもしれない) ため、
これはオペーク型のポインタでもあります。
C 言語のポインタ c_pointer
は、オペーク型である opaque_pointer
で
初期化されてます。これはエラーとなります。
pub fn main() anyerror!void {
var opaque_pointer: *c_void = undefined;
var c_pointer: [*c]c_void = opaque_pointer; // error
}
C 互換のポインタが指すことができるのは、C 互換のデータだけです。
C 互換のポインタは [*c]T
と書きます (ここで T
は任意の型を示す)。
以下の例で MyExternStruct
は、extern
と宣言されているので、
C 互換の構造体になります。
const MyStruct = struct {};
const MyExternStruct = extern struct {};
pub fn main() anyerror!void {
var a: *MyStruct = undefined; // ok
var b: [*c]MyExternStruct = undefined; // ok
var c: [*c]MyStruct = undefined; // error
}
このエラーコードが存在しますが説明がございません。
このエラーコードが存在しますが説明がございません。
このエラーコードが存在しますが説明がございません。
vtable
ポインタが指せるのはインタフェース・オブジェクトだけですが、
他のオブジェクトを指してしまっています。
次の例では、c
は正しく *vtable MyInterface
型と宣言されています。
これは、MyInterface を満たす構造体への vtable
ポインタ型を意味します。
一方 d
は、間違って *vtable MyStruct
型と宣言されています。
これは、特定の構造体 (この場合は MyStruct) への
vtable
ポインタ型を意味します。
このような宣言はできないためエラーとなります。
const MyInterface = interface {
fn foo() void;
};
const MyStruct = struct { // Implements MyInterface
fn foo(self: *MyStruct) void {}
};
pub fn main() anyerror!void {
var a = MyStruct{};
var b: *MyStruct = &a; // ok
var c: *vtable MyInterface = &a; // ok
var d: *vtable MyStruct = &a; // error
}
通常のポインタがインタフェースを指すことは出来ません。
代わりに vtable
ポインタを使ってください。
const MyInterface = interface {
fn foo() void;
};
pub fn main() anyerror!void {
var a: *vtable MyInterface = undefined; // ok
var b: *MyInterface = undefined; // error
}
packed struct 内のビットフィールドへのポインタは、 通常の実行時アドレスとは異なる特別な型となります。
次の例では bar
がそのようなポインタで、型は *align(:4:1) u4
です。
これは通常の実行時アドレスではなく、したがって整数型へ変換することは出来ません。
const MyPackedStruct = packed struct {
field1: u4,
field2: u4,
};
pub fn main() anyerror!void {
var my_data = MyPackedStruct{
.field1 = 1,
.field2 = 2,
};
var foo: usize = @ptrToInt(&my_data.field1);
var bar: *align(:4:1) u4 = &my_data.field2;
assert(bar.* == 2);
var baz: usize = @ptrToInt(&my_data.field2); // error
}
メモリ上に存在しないもののアドレスを取ろうとしています。
次の例では、array
は要素数 0 の配列であり、実体がメモリ上に存在しません。
array
のアドレスを取ろうとするとエラーになります。
pub fn main() anyerror!void {
var array = [0]u8{};
_ = @ptrToInt(&array); // error
}
@bitCast
を使った型変換では、変換前後のビット幅が同じである必要があります。
次の例では、1 バイトの整数を 4 バイトの浮動小数点型に変換しようとしています。 これはエラーとなります。
pub fn main() anyerror!void {
const foo: u8 = 42;
_ = @bitCast(f32, foo); // error
}
@bitCast
を使った型変換では、変換前後のビット幅が同じである必要があります。
次の例では、32 ビットの整数を 31 ビットの整数に変換しようとしています。 どちらも 4 バイトで表せる型ではありますが、ビット幅が違うためエラーとなります。
pub fn main() anyerror!void {
const foo: u32 = 42;
_ = @bitCast(u31, foo); // error
}
*void
型の変数は、サイズが 0 であり、実行時に実体がメモリ上に存在しないため、
情報を格納することが出来ません。
pub fn main() anyerror!void {
assert(@sizeOf(*void) == 0);
var foo: usize = 0x1000;
var bar: *void = undefined;
bar = @intToPtr(*void, foo); // error
}
@bitCast
を使って、データを変換できない型へ変換しようとしています。
通常の struct はメモリ上の配置が決まっていないため、
次の例では @bitCast
で buf
を MyStruct
へ変換しようとして
エラーとなります。
なお packed struct はメモリ上の配置が定義されています。
pub fn main() anyerror!void {
const buf = [4]u8{ 0xEF, 0xBE, 0xAD, 0xDE, };
const MyPackedStruct = packed struct {
field1: u32,
pub fn foo() void {}
};
const MyStruct = struct {
field1: u32,
pub fn foo() void {}
};
_ = @bitCast(MyPackedStruct, buf); // ok
_ = @bitCast(MyStruct, buf); // error
}
その型への型変換に @bitCast
は使えません。
代わりに、以下のコード例にあるように @intToEnum
が使えないか
検討してください。
const MyEnum = enum(u32) { A, B, C, D, };
pub fn main() anyerror!void {
const x = @intToEnum(MyEnum, @to(u32, 1)); // ok
assert(x == MyEnum.B);
const y = @bitCast(MyEnum, @to(u32, 1)); // error
}
特定のアドレスを指していない型から指す型へと、
@ptrCast
を使ってポインタの型変換を行おうとしています。
次の例では、EmptyStruct
のサイズは 0 です。
bar
がメモリ上で占める領域というものがないため、
&bar
は特定のアドレスを指していない事になります。
そのような bar
は、u8
のデータを指すアドレスである *u8
へと
変換することは出来ません。
pub fn main() anyerror!void {
const MyStruct = struct { field1: u8, };
var foo = MyStruct{ .field1 = 42, };
_ = @ptrCast(*u8, &foo); // ok
const EmptyStruct = struct {};
assert(@sizeOf(EmptyStruct) == 0);
var bar = EmptyStruct{};
_ = @ptrCast(*u8, &bar); // error
}
アライメント指定のあるポインタを型変換する場合、 バイト境界が大きくなるような変換はできません。
次の例では、align_1
は 1 バイト境界に、align_4
は 4 バイト境界に、
それぞれアラインされています。
align_1 = align_4;
はバイト境界が小さくなるような暗黙の型変換なので、
成功します。
align_4 = align_1;
はバイト境界が大きくなるような暗黙の型変換なので、
エラーとなります。
pub fn main() anyerror!void {
var align_1: *align(1) u32 = undefined;
var align_4: [*c]u32 = undefined;
align_1 = align_4; // ok
align_4 = align_1; // error
}
const ポインタを、const でないポインタへ型変換することは出来ません。
次の例では、&x
は *i32
型の const ポインタです。
これは、const でない *mut i32
型へは変換できません。
pub fn main() anyerror!void {
const x: i32 = 1234;
_ = @ptrCast(*mut i32, &x); // error
}
関数の戻り値型は、具体的に分かっている必要があります。 オペーク型 (具体的な内容が分からない型) は関数の戻り値型になれません。
次の例では、c_void
は具体的な内容が分からない型です。
これは関数の戻り値型になれません。
fn foo() u32 {
return 42;
}
pub fn main() anyerror!void {
const FnType1 = fn () u32; // ok
var bar: FnType1 = foo;
assert(bar() == 42);
const FnType2 = fn () c_void; // error
var baz: FnType2 = undefined;
}
スライスとは、配列のある範囲を表すものなので、配列から作る必要があります。
次の例では、1
は整数リテラルであって配列ではないため、
1
からスライスを作ることは出来ません。
pub fn main() anyerror!void {
const my_array = [4]u32{ 0, 1, 2, 3, };
_ = my_array[0..]; // ok
_ = 1[0..]; // error
}
ポインタのスライスは、終了地点を指定しなければいけません。
スライスは、ある配列の中の特定の範囲を表すものなので、
定義する際には範囲が具体的に分かっている必要があります。
次の例では、ptr1
は u32
の配列へのポインタです。
その型は *[4]u32
なので、配列のサイズは 4 であることが分かります。
my_slice2
の定義において、範囲は [0..]
と指定され、
終了地点が省略されています。
しかし対応する配列のサイズが分かっているので、
範囲の終了地点は暗黙のうちに配列の最後の要素となります。
ptr2
も同様に u32
配列へのポインタですが、型が [*]u32
なので、
配列のサイズを型情報から知ることは出来ません。
my_slice4
の定義においても、範囲は [0..]
と指定され、
終了地点が省略されています。
この場合、対応する配列のサイズが不明なため終了地点を推測することが
出来ないので、エラーとなります。
pub fn main() anyerror!void {
var my_array = [_]u32{ 0, 1, 2, 3, };
var ptr1 = &my_array;
assert(@TypeOf(ptr1) == *[4]u32);
var my_slice1 = ptr1[0..4];
var my_slice2 = ptr1[0..]; // ok
var ptr2 = @to([*]u32, &my_array);
assert(@TypeOf(ptr2) == [*]u32);
var my_slice3 = ptr2[0..4];
var my_slice4 = ptr2[0..]; // error
}
単一アイテムに対してスライスを作ることはできません。 これは、スライスとはある配列の中の特定の範囲を表すものだからです。
pub fn main() anyerror!void {
var my_array = [_]u32{ 0, 1, 2, 3, };
var my_slice1 = my_array[0..2]; // ok
var my_u32: u32 = 42;
var my_slice2 = (&my_u32)[0..2]; // error
}
ベクタの要素型は、整数型・浮動小数点型・ポインタ型・ブール型の いずれかである必要があります。
次の例では、@Vector(4, u32)
は要素型が u32
で 4 要素のベクタ型を表します。
u32
は整数型の一つなので、ベクタの要素型として使えます。
c
の型は comptime_int
で、通常の整数型とは異なるものであり、
ベクタの要素型としては使えません。
pub fn main() anyerror!void {
var u: u32 = 42;
var vec1 = @splat(4, u); // ok
assert(@TypeOf(vec1) == @Vector(4, u32));
const c = 42;
assert(@TypeOf(c) == comptime_int);
var vec2 = @splat(4, c); // error
}
整数型のビット幅は、1 から 65535 の間である必要があります。
pub fn main() anyerror!void {
var a: i1 = 0;
var b: u1 = 0;
var c: i65535 = 42;
var d: u65535 = 42;
var w: i0 = 0; // error
var x: u0 = 0; // error
var y: i65536 = 42; // error
var z: u65536 = 42; // error
}
このエラーコードが存在しますが説明がございません。
組込み関数 @truncate
の変換先の型のビット幅が、
変換元より大きくなってしまっています。
@truncate
は、変換元の整数の上位ビットを切り捨てて
変換先の型へと変換する関数です。
このため、変換元の整数型は、変換先以上のビット幅を持っている必要があります。
pub fn main() anyerror!void {
var my_u8: u8 = 42;
_ = @truncate(u7, my_u8);
_ = @truncate(u8, my_u8);
_ = @truncate(u9, my_u8); // error
}
このエラーコードが存在しますが説明がございません。
この共用体型には関連付けされた enum 型がありません。
タグ付き共用体でのみ可能な操作を、タグ付きでない共用体に対して 行っているというエラーです。 例えば以下のコード例にあるように、switch の分岐を共用体のヴァリアントで 行えるのは、タグ付き共用体だけです。
const MyTaggedUnion = union(enum) {
U8: u8,
U32: u32,
};
const MyUnion = union {
U8: u8,
U32: u32,
};
pub fn main() anyerror!void {
var x = MyTaggedUnion{ .U8 = 42 };
switch (x) { // ok
.U8 => {},
else => unreachable,
}
var y = MyUnion{ .U8 = 42 };
switch (y) { // error
.U8 => {},
else => unreachable,
}
}
switch
の条件式の型が不正です。
次の例では、x1
はオプション型、x2
は配列、x3
は構造体です。
これらは全て、switch
の条件式としては使えません。
const MyStruct = struct {
field1: u32,
};
pub fn main() anyerror!void {
var x1: ?u32 = 42;
switch (x1) { // error
else => {},
}
var x2 = [_]u32{ 0, 1, 2, 3, };
switch (x2) { // error
else => {},
}
var x3 = MyStruct{ .field1 = 42, };
switch (x3) { // error
else => {},
}
}
サイズの情報のない型から、サイズの情報を取得しようとしたエラーです。
次の例では、null
や undefined
の型にはサイズの情報がないため、
そのサイズを取得しようとしてエラーになります。
fn foo() usize {
return @sizeOf(@TypeOf(null)); // error
}
fn bar() usize {
return @sizeOf(@TypeOf(undefined)); // error
}
配列の要素になれる型には制限があります。
次のコードでは、配列の要素になれない型の例として、
null
型、undefined
型、およびインタフェース型を挙げています。
const MyInterface = interface {
field1: u32,
};
const MyStruct = struct {
field1: u32,
};
pub fn main() anyerror!void {
var foo = [_]@TypeOf(null){ null, }; // error
var bar = [_]@TypeOf(undefined){ undefined, }; // error
var myStruct = MyStruct{ .field1 = 42, };
var baz = [_]MyInterface{ myStruct, }; // error
}
スライスの要素になれる型には制限があります。
次のコードでは、スライスの要素になれない型の例として、
null
型、undefined
型、およびインタフェース型を挙げています。
const MyInterface = interface {
field1: u32,
};
const MyStruct = struct {
field1: u32,
};
pub fn main() anyerror!void {
var foo = []@TypeOf(null){ null, }; // error
var bar = []@TypeOf(undefined){ undefined, }; // error
var myStruct = MyStruct{ .field1 = 42, };
var baz = []MyInterface{ myStruct, }; // error
}
配列型でない値を配列であるかのようにインデックスでアクセスしたというエラーです。
次の例では、foo
は u8
型、bar
は *u8
型であり、
どちらも配列ではありません。
インデックス [1]
でアクセスしようとするとエラーになります。
pub fn main() anyerror!void {
var foo: u8 = 42;
_ = foo[1]; // error
var bar: *u8 = &foo;
_ = bar[1]; // error
}
間接参照演算子 .*
は、単一オブジェクトを指すポインタにのみ使えます。
次のコードは、単一オブジェクトを指すポインタでないものに
間接参照演算子を使っているエラーの例をいくつか示しています。
param
は [*]u32
型で、これはu32
の集まり (ただし個数は不明) を
指すポインタです。
export fn my_func(param: [*]u32) void {
param[0] = 42; // ok
_ = param.*; // error
}
pub fn main() anyerror!void {
var my_u32: u32 = 42;
my_u32.* = 1337; // error
'a'.* = 42; // error
var my_array = [4]u32{ 0, 1, 2, 3, };
assert((&my_array).*.len == 4);
_ = my_array.*.len; // error
}
オペーク型と noreturn
型はオプション型にできません。
オペーク型とは、内容が不明な型です。
次の例では、c_void
はそのような型の一つです。
pub fn main() anyerror!void {
var foo: ?u32 = undefined; // ok
var bar: ?c_void = undefined; // error
var baz: ?noreturn = undefined; // error
}
関数呼び出しにおいて、渡す実引数の数が間違っています。
次の例で、myStruct.add2(42, 1337)
は実引数を 3つ 渡している点に
注意してください。myStruct
が暗黙の第1引数となっています。
fn add1(a: u32) u32 {
return a + 1;
}
const MyStruct = struct {
fn add2(ms: MyStruct, a: u32) u32 {
return a + 2;
}
};
pub fn main() anyerror!void {
_ = add1(); // error
_ = add1(42, 1337); // error
var myStruct = MyStruct{};
_ = myStruct.add2(42); // ok
_ = myStruct.add2(42, 1337); // error
}
このエラーコードが存在しますが説明がございません。
このエラーコードが存在しますが説明がございません。
関数をエクスポートするためには、 関数の呼び出し規約を指定しておく必要があります。
関数の定義において呼び出し規約を指定するためには、以下の例にあるように、
extern
修飾子または callconv
を使います。
comptime {
const options1 = std.builtin.ExportOptions { .name = "fn1", };
const options2 = std.builtin.ExportOptions { .name = "fn2", };
const options3 = std.builtin.ExportOptions { .name = "fn3", };
const options4 = std.builtin.ExportOptions { .name = "fn4", };
@export(my_func1, options1);
@export(my_func2, options2);
@export(my_func3, options3);
@export(my_func4, options4); // error
}
extern fn my_func1() void {}
fn my_func2() callconv(.C) void {}
fn my_func3() callconv(.Stdcall) void {}
fn my_func4() void {}
このエラーコードが存在しますが説明がございません。
async
を使用して関数を非同期に呼び出す際には、
その関数の呼び出し規約に制限があります。
以下の例では、func3
と func4
は C 言語互換の呼び出し規約を使っており、
このため非同期に呼び出すことが出来ません。
なお、@frame() を使うと、使った関数が async
になります。
fn func1() void {
_ = @frame();
}
fn func2() callconv(.Async) void {
_ = @frame();
}
export fn func3() void { // error
_ = @frame();
}
fn func4() callconv(.C) void { // error
_ = @frame();
}
fn func5() callconv(.Stdcall) void { // error
_ = @frame();
}
pub fn main() anyerror!void {
_ = async func1();
_ = async func2();
_ = async func3();
_ = async func4();
_ = async func5();
}
演算子のオペランドが不正です。
以下の例では、ビット OR 演算子 |
をエラー型に、
加算演算子 +
を構造体に使おうとしており、どちらもエラーとなります。
pub const AB = error.A | error.B; // error
const MyStruct = struct { field1: u32, };
pub fn main() anyerror!void {
var x: AB = undefined;
var ms1 = MyStruct{ .field1 = 42, };
var ms2 = MyStruct{ .field1 = 1337, };
_ = ms1 + ms2; // error
}
ビット論理シフト演算子 (<<
と >>
) は、左辺オペランドが整数型、
右辺オペランドがコンパイル時計算可能である必要があります。
次の例では、foo
の型は comptime_int
であり、
これはコンパイル時計算可能です。
bar
の型は u8
で、これはコンパイル時計算可能ではありません。
pub fn main() anyerror!void {
_ = 0x10 << 2; // ok
const foo = 2;
assert(@TypeOf(foo) == comptime_int);
_ = 0x10 << foo; // ok
var bar: u8 = 2;
_ = 0x10 << bar; // error
}
演算子が、適用できない型の値に適用されています。
以下のコードに、そのような例を示しています。
my_error
はエラー型、foo
は関数ポインタで、
どちらも ==
演算子で等しいかどうか評価することができます。
しかし順序関係はないので、>
は使えません。
my_error_or_u32
のようなエラー共用体は、等しいかどうかの評価もできません。
配列の内容が等しいかどうか ==
で直接評価することは出来ませんが、
スライスに変換して標準ライブラリの std.mem.equal
で評価することができます。
fn foo() void {}
pub fn main() anyerror!void {
var my_error: anyerror = error.A;
_ = my_error == error.A; // ok
_ = my_error > error.A; // error
var my_error_or_u32: anyerror!u32 = error.A;
_ = my_error_or_u32 == error.A; // error
assert(@TypeOf(foo) == fn() void);
_ = foo == foo; // ok
_ = foo > foo; // error
var array1 = [4]u32{ 0, 1, 2, 3, };
var array2 = [4]u32{ 0, 1, 2, 3, };
assert(std.mem.equal(u32, array1[0..], array2[0..]) == true);
_ = array1 == array2; // error
}
異なるエラー型の値が等しいかを評価するとき、 それらの型の間で共通のエラー種別が存在する必要があります。
共通のエラー種別がなければ、値が等しくなることは決してないので、 そのような評価は通常はプログラムのバグです。
pub fn main() anyerror!void {
const ErrorSet1 = error{ A, B, };
const ErrorSet2 = error{ A, B, C, };
const ErrorSet3 = error{ X, Y, };
var foo = ErrorSet1.A;
assert(foo == ErrorSet2.A);
assert(foo != ErrorSet2.C);
_ = foo == ErrorSet3.X; // error
}
null
との比較ができるのは、オプション型の値だけです。
次の例では、foo
はオプション型であり、null
と比較できます。
しかし &foo
は (オプション型への) ポインタであり、
それ自体はオプション型ではありません。
pub fn main() anyerror!void {
var foo: ?u32 = null;
assert(foo == null);
foo = 42;
assert(foo != null);
_ = &foo == null; // error
var bar: u32 = 42;
_ = bar == null; // error
_ = &bar == null; // error
}
構造体へのポインタからインタフェースへのポインタへと暗黙の型変換を行う際に、
構造体のあるメソッドの self
ポインタ引数の属性を破棄しているという
エラーです。
次の例では、inc
メソッドはインスタンスを変更するので、
その self
引数は mut
である必要があります。
b
の初期化において MyStruct
へのポインタが
mut
でない *vtable MyInterface
型へと暗黙の型変換をされていますが、
このため、b
から inc
を呼び出す時に渡す MyStruct
へのポインタが
mut
になりません。これはエラーとなります。
const MyStruct = struct {
field1: u32,
fn inc(self: *mut MyStruct) void {
self.field1 += 1;
}
};
const MyInterface = interface {
fn inc() void;
};
pub fn main() anyerror!void {
var my_struct = MyStruct{ .field1 = 42, };
var a: *mut vtable MyInterface = &mut my_struct; // ok
var b: *vtable MyInterface = &mut my_struct; // error
}
このエラーコードが存在しますが説明がございません。
このエラーコードが存在しますが説明がございません。
このエラーコードが存在しますが説明がございません。
void でないフィールドを持つ共用体は実行時に型変換できません。
列挙型からタグ付き共用体へは、共用体のヴァリアントが void
型など
コンパイル時計算可能な場合のみ、暗黙の型変換が行われます。
const MyEnum = enum { A, B, C, };
const MyTaggedUnion1 = union(MyEnum) {
A,
B,
C,
};
const MyTaggedUnion2 = union(MyEnum) {
A: u32,
B,
C,
};
pub fn main() anyerror!void {
var enum_a = MyEnum.A;
var a: MyTaggedUnion1 = enum_a; // ok
var b: MyTaggedUnion2 = enum_a; // error
}
共用体への型変換では、ヴァリアントの値を初期化する必要があります。
次の例では、タグ付き共用体 MyTaggedUnion
のヴァリアント A
は
u32
の値を格納します。
このため、MyTaggedUnion
型の値をヴァリアント A
で初期化する場合、
u32
の値を与える必要があります。
const MyEnum = enum { A, B, C, };
const MyTaggedUnion = union(MyEnum) {
A: u32,
B,
C,
};
pub fn main() anyerror!void {
var x: MyTaggedUnion = MyTaggedUnion{ .A = 42 }; // ok
var y: MyTaggedUnion = MyEnum.B; // ok
var z: MyTaggedUnion = MyEnum.A; // error
}
メソッドは、属する構造体の値またはそれへのポインタを第1引数として 受け取ることを期待していますが、そうなっていないというエラーです。
次の例では、インタフェース型の y
は MyStruct2
の値で初期化されているので、
y
のメソッドは MyStruct2
の値またはそれへのポインタを
受け取ることを期待します。
実際に、my_func
の self
仮引数がそのようになっています。
一方、z
も同様に MyStruct1
の値で初期化されているので、そのメソッドには
MyStruct1
の値またはそれへのポインタが渡されることになりますが、
my_func
はそのどちらも受け取るようになっていません。これはエラーです。
ここで、x
の初期化においては、my_func
はそのような値やポインタを
受け取ることは期待されていない点に注意してください。
MyStruct1
の my_func
には self
仮引数がありませんが、
それが必ずしもバグだとは限らないのです。
const MyInterface = interface {
fn my_func() void;
};
const MyStruct1 = struct {
fn my_func() void {} // !!!
};
const MyStruct2 = struct {
fn my_func(self: *MyStruct2) void {}
};
pub fn main() anyerror!void {
var x = MyStruct1{}; // ok
var y: MyInterface = MyStruct2{}; // ok
var z: MyInterface = MyStruct1{}; // error
}
このエラーコードが存在しますが説明がございません。
構造体・列挙型・共用体のいずれかの型が期待されている箇所で、 そのような型が得られなかったというエラーです。
次の例では、組込み関数 @hasDecl
は構造体・列挙型・共用体のいずれかの型を
第1引数として受け取り、
第2引数で指定した宣言がその型に含まれているかどうかを返します。
bool
型はそのいずれの型でもないので、2つ目の @hasDecl
はエラーとなります。
const MyStruct = struct {
pub var field1: u32;
};
pub fn main() anyerror!void {
assert(@hasDecl(MyStruct, "field1")); // ok
assert(@hasDecl(bool, "field1")); // error
}
このエラーコードが存在しますが説明がございません。
ジェネリック関数の戻り値型が決定できません。
次の例では、関数 generic_function
の戻り値型は引数によって決まるので、
この関数自体には特定の戻り値型がありません。
fn non_generic_function() u32 {
return 42;
}
fn generic_function(a: anytype) anytype {
return a;
}
pub fn main() anyerror!void {
assert(@TypeOf(non_generic_function).ReturnType == u32); // ok
_ = @TypeOf(generic_function).ReturnType; // error
}
switch
中で、異なる型の値を1つの変数でキャプチャーしようとしています。
次の例では、MyUnion
のヴァリアント A
または C
の値を
capture2
という1つの変数でキャプチャーしようとしていますが、
これらは型が異なります (u8
と u32
)。
このため capture2
の型が決定できず、エラーとなります。
ここで capture1
の型は u8
に決定できる点に注意してください。
const MyUnion = union(enum) {
A: u8,
B: u8,
C: u32,
};
pub fn main() anyerror!void {
var x = MyUnion{ .A = 42 };
switch (x) {
.A, .B => |capture1| { // ok
assert(@TypeOf(capture1) == u8);
},
else => {},
}
switch (x) {
.A, .C => |capture2| {}, // error
else => {},
}
}
このエラーコードが存在しますが説明がございません。
関数の戻り値型が不正です。
次の例では、MyInterface
はインタフェース型で、
MyOpaqueType
はオペーク型 (内容が不明な型) です。
どちらも、関数の戻り値型にはできません。
const MyInterface = interface {};
const MyStruct = struct {};
fn func1() MyInterface { // error
return MyStruct{};
}
const MyOpaqueType = @OpaqueType();
fn func2() !MyOpaqueType { // error
return error.SomeError;
}
このエラーコードが存在しますが説明がございません。
noreturn
は関数の引数に使えません。
fn my_func(a: noreturn) void { // error
}
その呼出し規約を使う関数は、その型の仮引数を受け取ることができません。
次の例では、func2
および func3
関数は、それぞれ export
および
callconv(.C)
の指定により、C 言語互換の呼出し規約を使います。
このような関数は anytype
型の仮引数を受け取ることができません。
fn func1(a: anytype) u32 { // ok
return 42;
}
export fn func2(a: anytype) u32 { // error
return 42;
}
fn func3(a: anytype) callconv(.C) u32 { // error
return 42;
}
C 言語互換の呼出し規約を使う関数が受け取ることのできない引数の型には他に、
列挙型・構造体・共用体・*void
などがあります。
async
になれない関数が async
と指定されている、というエラーです。
次の例では、func1
は export
されているので C 言語互換の呼出し規約を
使うことになり、よって async
にはなれません。
callconv(.Async)
によって async
となるよう指定されていますが、
これはエラーとなります。
func3
は、async
でない関数型の変数 foo
に代入されるので、
async
にはなれません。
しかし関数内に suspend
を含むため、async
である必要があります。
これはエラーとなります。
export fn func1() callconv(.Async) void { // error
}
fn func2() void {}
fn func3() void {
suspend;
}
pub fn main() anyerror!void {
var foo: fn () void = undefined;
foo = func2; // ok
foo = func3; // error
}
ビット幅が 0 の変数は、実行時にメモリ上に存在しないため、 アラインすることができません。
次の例では、main
中の変数は 4 つ全て、ビット幅が 0 です。
const EmptyStruct = struct {};
const EmptyArray = [0]u8;
pub fn main() anyerror!void {
var a: EmptyStruct = undefined; // ok
var b: EmptyArray = undefined; // ok
var x: EmptyStruct align(4) = undefined; // error
var y: EmptyArray align(4) = undefined; // error
}
浮動小数点型のビット幅が不正です。
Zen 言語は、16・32・64・128 ビットの浮動小数点型のみサポートしています。
pub fn main() anyerror!void {
var a: f16 = 158.3;
var b: f32 = 158.3;
var c: f64 = 158.3;
var d: f128 = 158.3;
const My32BitFloat = @Type(std.builtin.TypeInfo{
.Float = std.builtin.TypeInfo.Float{
.bits = 32 // ok
}
});
const My42BitFloat = @Type(std.builtin.TypeInfo{
.Float = std.builtin.TypeInfo.Float{
.bits = 42 // error
}
});
}
☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2020 connectFree Corporation. All rights reserved. | 特定商取引法に基づく表示
Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.