authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-01-29 21:47:26-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-01-29 22:30:30-05:00
log581edd643fb18a66c472f77e2f8cd3f4cea524a2
treea03f6a3ade952729456b94584f21d4beb51a4802
parent9c328b42916d463465b134457c7f13b5c65da406
signaturelock-open Commit is signed but in an unrecognized format.

backport copy elision changes

This commit contains everything from the copy-elision-2 branch that does not have to do with copy elision directly, but is generally useful for master branch. * All const values know their parents, when applicable, not just structs and unions. * Null pointers in const values are represented explicitly, rather than as a HardCodedAddr value of 0. * Rename "maybe" to "optional" in various code locations. * Separate DeclVarSrc and DeclVarGen * Separate PtrCastSrc and PtrCastGen * Separate CmpxchgSrc and CmpxchgGen * Represent optional error set as an integer, using the 0 value. In a const value, it uses nullptr. * Introduce type_has_one_possible_value and use it where applicable. * Fix debug builds not setting memory to 0xaa when storing undefined. * Separate the type of a variable from the const value of a variable. * Use copy_const_val where appropriate. * Rearrange structs to pack data more efficiently. * Move test/cases/* to test/behavior/* * Use `std.debug.assertOrPanic` in behavior tests instead of `std.debug.assert`. * Fix outdated slice syntax in docs.

181 files changed, 10595 insertions(+), 9692 deletions(-)

build.zig+2-3
......@@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void {
104104 }
105105 const modes = chosen_modes[0..chosen_mode_index];
106106
107 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes));
107 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));
108108
109109 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));
110110
......@@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
299299 } else if (exe.target.isFreeBSD()) {
300300 try addCxxKnownPath(b, ctx, exe, "libc++.a", null);
301301 exe.linkSystemLibrary("pthread");
302 }
303 else if (exe.target.isDarwin()) {
302 } else if (exe.target.isDarwin()) {
304303 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
305304 // Compiler is GCC.
306305 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
doc/langref.html.in+7-6
......@@ -4327,7 +4327,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
43274327 <p>
43284328 For example, if we were to introduce another function to the above snippet:
43294329 </p>
4330 {#code_begin|test_err|unable to evaluate constant expression#}
4330 {#code_begin|test_err|values of type 'type' must be comptime known#}
43314331fn max(comptime T: type, a: T, b: T) T {
43324332 return if (a > b) a else b;
43334333}
......@@ -5905,13 +5905,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }
59055905 This function is a low level intrinsic with no safety mechanisms. Most code
59065906 should not use this function, instead using something like this:
59075907 </p>
5908 <pre>{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>
5908 <pre>{#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>
59095909 <p>
59105910 The optimizer is intelligent enough to turn the above snippet into a memcpy.
59115911 </p>
59125912 <p>There is also a standard library function for this:</p>
59135913 <pre>{#syntax#}const mem = @import("std").mem;
5914mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
5914mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}</pre>
59155915 {#header_close#}
59165916
59175917 {#header_open|@memset#}
......@@ -5923,7 +5923,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
59235923 This function is a low level intrinsic with no safety mechanisms. Most
59245924 code should not use this function, instead using something like this:
59255925 </p>
5926 <pre>{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}</pre>
5926 <pre>{#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}</pre>
59275927 <p>
59285928 The optimizer is intelligent enough to turn the above snippet into a memset.
59295929 </p>
......@@ -6592,9 +6592,10 @@ pub const TypeInfo = union(TypeId) {
65926592 {#header_close#}
65936593
65946594 {#header_open|@typeName#}
6595 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
6595 <pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre>
65966596 <p>
6597 This function returns the string representation of a type.
6597 This function returns the string representation of a type, as
6598 an array. It is equivalent to a string literal of the type name.
65986599 </p>
65996600
66006601 {#header_close#}
src/all_types.hpp+115-50
......@@ -56,9 +56,6 @@ struct IrExecutable {
5656 size_t next_debug_id;
5757 size_t *backward_branch_count;
5858 size_t backward_branch_quota;
59 bool invalid;
60 bool is_inline;
61 bool is_generic_instantiation;
6259 ZigFn *fn_entry;
6360 Buf *c_import_buf;
6461 AstNode *source_node;
......@@ -78,6 +75,10 @@ struct IrExecutable {
7875 IrBasicBlock *coro_suspend_block;
7976 IrBasicBlock *coro_final_cleanup_block;
8077 ZigVar *coro_allocator_var;
78
79 bool invalid;
80 bool is_inline;
81 bool is_generic_instantiation;
8182};
8283
8384enum OutType {
......@@ -90,6 +91,9 @@ enum OutType {
9091enum ConstParentId {
9192 ConstParentIdNone,
9293 ConstParentIdStruct,
94 ConstParentIdErrUnionCode,
95 ConstParentIdErrUnionPayload,
96 ConstParentIdOptionalPayload,
9397 ConstParentIdArray,
9498 ConstParentIdUnion,
9599 ConstParentIdScalar,
......@@ -107,6 +111,15 @@ struct ConstParent {
107111 ConstExprValue *struct_val;
108112 size_t field_index;
109113 } p_struct;
114 struct {
115 ConstExprValue *err_union_val;
116 } p_err_union_code;
117 struct {
118 ConstExprValue *err_union_val;
119 } p_err_union_payload;
120 struct {
121 ConstExprValue *optional_val;
122 } p_optional_payload;
110123 struct {
111124 ConstExprValue *union_val;
112125 } p_union;
......@@ -118,13 +131,11 @@ struct ConstParent {
118131
119132struct ConstStructValue {
120133 ConstExprValue *fields;
121 ConstParent parent;
122134};
123135
124136struct ConstUnionValue {
125137 BigInt tag;
126138 ConstExprValue *payload;
127 ConstParent parent;
128139};
129140
130141enum ConstArraySpecial {
......@@ -138,7 +149,6 @@ struct ConstArrayValue {
138149 union {
139150 struct {
140151 ConstExprValue *elements;
141 ConstParent parent;
142152 } s_none;
143153 Buf *s_buf;
144154 } data;
......@@ -153,19 +163,29 @@ enum ConstPtrSpecial {
153163 ConstPtrSpecialBaseArray,
154164 // The pointer points to a field in an underlying struct.
155165 ConstPtrSpecialBaseStruct,
166 // The pointer points to the error set field of an error union
167 ConstPtrSpecialBaseErrorUnionCode,
168 // The pointer points to the payload field of an error union
169 ConstPtrSpecialBaseErrorUnionPayload,
170 // The pointer points to the payload field of an optional
171 ConstPtrSpecialBaseOptionalPayload,
156172 // This means that we did a compile-time pointer reinterpret and we cannot
157173 // understand the value of pointee at compile time. However, we will still
158174 // emit a binary with a compile time known address.
159175 // In this case index is the numeric address value.
160 // We also use this for null pointer. We need the data layout for ConstCastOnly == true
161 // types to be the same, so all optionals of pointer types use x_ptr
162 // instead of x_optional
163176 ConstPtrSpecialHardCodedAddr,
164177 // This means that the pointer represents memory of assigning to _.
165178 // That is, storing discards the data, and loading is invalid.
166179 ConstPtrSpecialDiscard,
167180 // This is actually a function.
168181 ConstPtrSpecialFunction,
182 // This means the pointer is null. This is only allowed when the type is ?*T.
183 // We use this instead of ConstPtrSpecialHardCodedAddr because often we check
184 // for that value to avoid doing comptime work.
185 // We need the data layout for ConstCastOnly == true
186 // types to be the same, so all optionals of pointer types use x_ptr
187 // instead of x_optional.
188 ConstPtrSpecialNull,
169189};
170190
171191enum ConstPtrMut {
......@@ -199,6 +219,15 @@ struct ConstPtrValue {
199219 ConstExprValue *struct_val;
200220 size_t field_index;
201221 } base_struct;
222 struct {
223 ConstExprValue *err_union_val;
224 } base_err_union_code;
225 struct {
226 ConstExprValue *err_union_val;
227 } base_err_union_payload;
228 struct {
229 ConstExprValue *optional_val;
230 } base_optional_payload;
202231 struct {
203232 uint64_t addr;
204233 } hard_coded_addr;
......@@ -209,7 +238,7 @@ struct ConstPtrValue {
209238};
210239
211240struct ConstErrValue {
212 ErrorTableEntry *err;
241 ConstExprValue *error_set;
213242 ConstExprValue *payload;
214243};
215244
......@@ -265,6 +294,7 @@ struct ConstGlobalRefs {
265294struct ConstExprValue {
266295 ZigType *type;
267296 ConstValSpecial special;
297 ConstParent parent;
268298 ConstGlobalRefs *global_refs;
269299
270300 union {
......@@ -433,7 +463,7 @@ enum NodeType {
433463 NodeTypeArrayType,
434464 NodeTypeErrorType,
435465 NodeTypeIfErrorExpr,
436 NodeTypeTestExpr,
466 NodeTypeIfOptional,
437467 NodeTypeErrorSetDecl,
438468 NodeTypeCancel,
439469 NodeTypeResume,
......@@ -677,7 +707,7 @@ struct AstNodeUse {
677707 AstNode *expr;
678708
679709 TldResolution resolution;
680 IrInstruction *value;
710 ConstExprValue *value;
681711};
682712
683713struct AstNodeIfBoolExpr {
......@@ -1610,7 +1640,7 @@ struct CodeGen {
16101640 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
16111641 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
16121642 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
1613 HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
1643 HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
16141644 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
16151645 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
16161646 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
......@@ -1802,10 +1832,9 @@ enum VarLinkage {
18021832
18031833struct ZigVar {
18041834 Buf name;
1805 ConstExprValue *value;
1835 ConstExprValue *const_value;
1836 ZigType *var_type;
18061837 LLVMValueRef value_ref;
1807 bool src_is_const;
1808 bool gen_is_const;
18091838 IrInstruction *is_comptime;
18101839 // which node is the declaration of the variable
18111840 AstNode *decl_node;
......@@ -1815,17 +1844,21 @@ struct ZigVar {
18151844 Scope *parent_scope;
18161845 Scope *child_scope;
18171846 LLVMValueRef param_value_ref;
1818 bool shadowable;
18191847 size_t mem_slot_index;
18201848 IrExecutable *owner_exec;
18211849 size_t ref_count;
1822 VarLinkage linkage;
1823 uint32_t align_bytes;
18241850
18251851 // In an inline loop, multiple variables may be created,
18261852 // In this case, a reference to a variable should follow
18271853 // this pointer to the redefined variable.
18281854 ZigVar *next_var;
1855
1856 uint32_t align_bytes;
1857 VarLinkage linkage;
1858
1859 bool shadowable;
1860 bool src_is_const;
1861 bool gen_is_const;
18291862};
18301863
18311864struct ErrorTableEntry {
......@@ -1891,10 +1924,11 @@ struct ScopeBlock {
18911924 ZigList<IrInstruction *> *incoming_values;
18921925 ZigList<IrBasicBlock *> *incoming_blocks;
18931926
1894 bool safety_off;
18951927 AstNode *safety_set_node;
1896 bool fast_math_on;
18971928 AstNode *fast_math_set_node;
1929
1930 bool safety_off;
1931 bool fast_math_on;
18981932};
18991933
19001934// This scope is created from every defer expression.
......@@ -2030,8 +2064,19 @@ struct IrBasicBlock {
20302064 IrInstruction *must_be_comptime_source_instr;
20312065};
20322066
2067// These instructions are in transition to having "pass 1" instructions
2068// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
2069// and pass 2 are suffixed with Gen.
2070// Once all instructions are separated in this way, they'll have different
2071// base types for better type safety.
2072// Src instructions are generated by ir_gen_* functions in ir.cpp from AST.
2073// ir_analyze_* functions consume Src instructions and produce Gen instructions.
2074// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
2075// Src instructions do not have type information; Gen instructions do.
20332076enum IrInstructionId {
20342077 IrInstructionIdInvalid,
2078 IrInstructionIdDeclVarSrc,
2079 IrInstructionIdDeclVarGen,
20352080 IrInstructionIdBr,
20362081 IrInstructionIdCondBr,
20372082 IrInstructionIdSwitchBr,
......@@ -2040,7 +2085,6 @@ enum IrInstructionId {
20402085 IrInstructionIdPhi,
20412086 IrInstructionIdUnOp,
20422087 IrInstructionIdBinOp,
2043 IrInstructionIdDeclVar,
20442088 IrInstructionIdLoadPtr,
20452089 IrInstructionIdStorePtr,
20462090 IrInstructionIdFieldPtr,
......@@ -2069,7 +2113,7 @@ enum IrInstructionId {
20692113 IrInstructionIdAsm,
20702114 IrInstructionIdSizeOf,
20712115 IrInstructionIdTestNonNull,
2072 IrInstructionIdUnwrapOptional,
2116 IrInstructionIdOptionalUnwrapPtr,
20732117 IrInstructionIdOptionalWrap,
20742118 IrInstructionIdUnionTag,
20752119 IrInstructionIdClz,
......@@ -2085,7 +2129,8 @@ enum IrInstructionId {
20852129 IrInstructionIdCompileLog,
20862130 IrInstructionIdErrName,
20872131 IrInstructionIdEmbedFile,
2088 IrInstructionIdCmpxchg,
2132 IrInstructionIdCmpxchgSrc,
2133 IrInstructionIdCmpxchgGen,
20892134 IrInstructionIdFence,
20902135 IrInstructionIdTruncate,
20912136 IrInstructionIdIntCast,
......@@ -2114,7 +2159,8 @@ enum IrInstructionId {
21142159 IrInstructionIdErrWrapPayload,
21152160 IrInstructionIdFnProto,
21162161 IrInstructionIdTestComptime,
2117 IrInstructionIdPtrCast,
2162 IrInstructionIdPtrCastSrc,
2163 IrInstructionIdPtrCastGen,
21182164 IrInstructionIdBitCast,
21192165 IrInstructionIdWidenOrShorten,
21202166 IrInstructionIdIntToPtr,
......@@ -2194,6 +2240,22 @@ struct IrInstruction {
21942240 bool is_gen;
21952241};
21962242
2243struct IrInstructionDeclVarSrc {
2244 IrInstruction base;
2245
2246 ZigVar *var;
2247 IrInstruction *var_type;
2248 IrInstruction *align_value;
2249 IrInstruction *init_value;
2250};
2251
2252struct IrInstructionDeclVarGen {
2253 IrInstruction base;
2254
2255 ZigVar *var;
2256 IrInstruction *init_value;
2257};
2258
21972259struct IrInstructionCondBr {
21982260 IrInstruction base;
21992261
......@@ -2302,20 +2364,11 @@ struct IrInstructionBinOp {
23022364 IrInstruction base;
23032365
23042366 IrInstruction *op1;
2305 IrBinOp op_id;
23062367 IrInstruction *op2;
2368 IrBinOp op_id;
23072369 bool safety_check_on;
23082370};
23092371
2310struct IrInstructionDeclVar {
2311 IrInstruction base;
2312
2313 ZigVar *var;
2314 IrInstruction *var_type;
2315 IrInstruction *align_value;
2316 IrInstruction *init_value;
2317};
2318
23192372struct IrInstructionLoadPtr {
23202373 IrInstruction base;
23212374
......@@ -2335,7 +2388,6 @@ struct IrInstructionFieldPtr {
23352388 IrInstruction *container_ptr;
23362389 Buf *field_name_buffer;
23372390 IrInstruction *field_name_expr;
2338 bool is_const;
23392391};
23402392
23412393struct IrInstructionStructFieldPtr {
......@@ -2378,13 +2430,13 @@ struct IrInstructionCall {
23782430 ZigFn *fn_entry;
23792431 size_t arg_count;
23802432 IrInstruction **args;
2381 bool is_comptime;
23822433 LLVMValueRef tmp_ptr;
2383 FnInline fn_inline;
2384 bool is_async;
23852434
23862435 IrInstruction *async_allocator;
23872436 IrInstruction *new_stack;
2437 FnInline fn_inline;
2438 bool is_async;
2439 bool is_comptime;
23882440};
23892441
23902442struct IrInstructionConst {
......@@ -2527,9 +2579,9 @@ struct IrInstructionSliceType {
25272579 IrInstruction base;
25282580
25292581 IrInstruction *align_value;
2582 IrInstruction *child_type;
25302583 bool is_const;
25312584 bool is_volatile;
2532 IrInstruction *child_type;
25332585};
25342586
25352587struct IrInstructionAsm {
......@@ -2557,10 +2609,12 @@ struct IrInstructionTestNonNull {
25572609 IrInstruction *value;
25582610};
25592611
2560struct IrInstructionUnwrapOptional {
2612// Takes a pointer to an optional value, returns a pointer
2613// to the payload.
2614struct IrInstructionOptionalUnwrapPtr {
25612615 IrInstruction base;
25622616
2563 IrInstruction *value;
2617 IrInstruction *base_ptr;
25642618 bool safety_check_on;
25652619};
25662620
......@@ -2651,7 +2705,7 @@ struct IrInstructionEmbedFile {
26512705 IrInstruction *name;
26522706};
26532707
2654struct IrInstructionCmpxchg {
2708struct IrInstructionCmpxchgSrc {
26552709 IrInstruction base;
26562710
26572711 IrInstruction *type_value;
......@@ -2661,14 +2715,19 @@ struct IrInstructionCmpxchg {
26612715 IrInstruction *success_order_value;
26622716 IrInstruction *failure_order_value;
26632717
2664 // if this instruction gets to runtime then we know these values:
2665 ZigType *type;
2666 AtomicOrder success_order;
2667 AtomicOrder failure_order;
2668
26692718 bool is_weak;
2719};
26702720
2721struct IrInstructionCmpxchgGen {
2722 IrInstruction base;
2723
2724 IrInstruction *ptr;
2725 IrInstruction *cmp_value;
2726 IrInstruction *new_value;
26712727 LLVMValueRef tmp_ptr;
2728 AtomicOrder success_order;
2729 AtomicOrder failure_order;
2730 bool is_weak;
26722731};
26732732
26742733struct IrInstructionFence {
......@@ -2851,7 +2910,7 @@ struct IrInstructionTestErr {
28512910struct IrInstructionUnwrapErrCode {
28522911 IrInstruction base;
28532912
2854 IrInstruction *value;
2913 IrInstruction *err_union;
28552914};
28562915
28572916struct IrInstructionUnwrapErrPayload {
......@@ -2899,13 +2958,19 @@ struct IrInstructionTestComptime {
28992958 IrInstruction *value;
29002959};
29012960
2902struct IrInstructionPtrCast {
2961struct IrInstructionPtrCastSrc {
29032962 IrInstruction base;
29042963
29052964 IrInstruction *dest_type;
29062965 IrInstruction *ptr;
29072966};
29082967
2968struct IrInstructionPtrCastGen {
2969 IrInstruction base;
2970
2971 IrInstruction *ptr;
2972};
2973
29092974struct IrInstructionBitCast {
29102975 IrInstruction base;
29112976
src/analyze.cpp+213-84
......@@ -570,7 +570,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
570570 if (child_type->zero_bits) {
571571 entry->type_ref = LLVMInt1Type();
572572 entry->di_type = g->builtin_types.entry_bool->di_type;
573 } else if (type_is_codegen_pointer(child_type)) {
573 } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
574574 assert(child_type->di_type);
575575 // this is an optimization but also is necessary for calling C
576576 // functions where all pointers are maybe pointers
......@@ -1278,7 +1278,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
12781278 return entry;
12791279}
12801280
1281static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {
1281static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
1282 Buf *type_name)
1283{
12821284 size_t backward_branch_count = 0;
12831285 return ir_eval_const_value(g, scope, node, type_entry,
12841286 &backward_branch_count, default_backward_branch_quota,
......@@ -1286,12 +1288,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod
12861288}
12871289
12881290ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1289 IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1290 if (result->value.type->id == ZigTypeIdInvalid)
1291 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1292 if (type_is_invalid(result->type))
12911293 return g->builtin_types.entry_invalid;
12921294
1293 assert(result->value.special != ConstValSpecialRuntime);
1294 return result->value.data.x_type;
1295 assert(result->special != ConstValSpecialRuntime);
1296 return result->data.x_type;
12951297}
12961298
12971299ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
......@@ -1342,11 +1344,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
13421344}
13431345
13441346static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
1345 IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
1346 if (type_is_invalid(align_result->value.type))
1347 ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
1348 if (type_is_invalid(align_result->type))
13471349 return false;
13481350
1349 uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);
1351 uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint);
13501352 if (align_bytes == 0) {
13511353 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
13521354 return false;
......@@ -1364,12 +1366,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
13641366 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
13651367 PtrLenUnknown, 0, 0, 0);
13661368 ZigType *str_type = get_slice_type(g, ptr_type);
1367 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
1368 if (type_is_invalid(instr->value.type))
1369 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
1370 if (type_is_invalid(result_val->type))
13691371 return false;
13701372
1371 ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];
1372 ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];
1373 ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
1374 ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
13731375
13741376 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
13751377 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
......@@ -2504,20 +2506,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
25042506 // In this first pass we resolve explicit tag values.
25052507 // In a second pass we will fill in the unspecified ones.
25062508 if (tag_value != nullptr) {
2507 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2508 if (result_inst->value.type->id == ZigTypeIdInvalid) {
2509 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2510 if (type_is_invalid(result->type)) {
25092511 enum_type->data.enumeration.is_invalid = true;
25102512 continue;
25112513 }
2512 assert(result_inst->value.special != ConstValSpecialRuntime);
2513 assert(result_inst->value.type->id == ZigTypeIdInt ||
2514 result_inst->value.type->id == ZigTypeIdComptimeInt);
2515 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
2514 assert(result->special != ConstValSpecialRuntime);
2515 assert(result->type->id == ZigTypeIdInt ||
2516 result->type->id == ZigTypeIdComptimeInt);
2517 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
25162518 if (entry == nullptr) {
2517 bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);
2519 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
25182520 } else {
25192521 Buf *val_buf = buf_alloc();
2520 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
2522 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
25212523
25222524 ErrorMsg *msg = add_node_error(g, tag_value,
25232525 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
......@@ -2944,19 +2946,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
29442946 // In a second pass we will fill in the unspecified ones.
29452947 if (tag_value != nullptr) {
29462948 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
2947 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2948 if (result_inst->value.type->id == ZigTypeIdInvalid) {
2949 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2950 if (type_is_invalid(result->type)) {
29492951 union_type->data.unionation.is_invalid = true;
29502952 continue;
29512953 }
2952 assert(result_inst->value.special != ConstValSpecialRuntime);
2953 assert(result_inst->value.type->id == ZigTypeIdInt);
2954 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
2954 assert(result->special != ConstValSpecialRuntime);
2955 assert(result->type->id == ZigTypeIdInt);
2956 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
29552957 if (entry == nullptr) {
2956 bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint);
2958 bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint);
29572959 } else {
29582960 Buf *val_buf = buf_alloc();
2959 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
2961 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
29602962
29612963 ErrorMsg *msg = add_node_error(g, tag_value,
29622964 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
......@@ -3419,7 +3421,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
34193421 resolve_top_level_decl(g, tld, false, tld->source_node);
34203422 assert(tld->id == TldIdVar);
34213423 TldVar *tld_var = (TldVar *)tld;
3422 tld_var->var->value = value;
3424 tld_var->var->const_value = value;
3425 tld_var->var->var_type = value->type;
34233426 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
34243427}
34253428
......@@ -3513,7 +3516,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
35133516 case NodeTypeArrayType:
35143517 case NodeTypeErrorType:
35153518 case NodeTypeIfErrorExpr:
3516 case NodeTypeTestExpr:
3519 case NodeTypeIfOptional:
35173520 case NodeTypeErrorSetDecl:
35183521 case NodeTypeCancel:
35193522 case NodeTypeResume:
......@@ -3582,13 +3585,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
35823585// Set name to nullptr to make the variable anonymous (not visible to programmer).
35833586// TODO merge with definition of add_local_var in ir.cpp
35843587ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
3585 bool is_const, ConstExprValue *value, Tld *src_tld)
3588 bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type)
35863589{
35873590 Error err;
3588 assert(value);
3591 assert(const_value != nullptr);
3592 assert(var_type != nullptr);
35893593
35903594 ZigVar *variable_entry = allocate<ZigVar>(1);
3591 variable_entry->value = value;
3595 variable_entry->const_value = const_value;
3596 variable_entry->var_type = var_type;
35923597 variable_entry->parent_scope = parent_scope;
35933598 variable_entry->shadowable = false;
35943599 variable_entry->mem_slot_index = SIZE_MAX;
......@@ -3597,23 +3602,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
35973602 assert(name);
35983603 buf_init_from_buf(&variable_entry->name, name);
35993604
3600 if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {
3601 variable_entry->value->type = g->builtin_types.entry_invalid;
3605 if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
3606 variable_entry->var_type = g->builtin_types.entry_invalid;
36023607 } else {
3603 variable_entry->align_bytes = get_abi_alignment(g, value->type);
3608 variable_entry->align_bytes = get_abi_alignment(g, var_type);
36043609
36053610 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
36063611 if (existing_var && !existing_var->shadowable) {
36073612 ErrorMsg *msg = add_node_error(g, source_node,
36083613 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
36093614 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3610 variable_entry->value->type = g->builtin_types.entry_invalid;
3615 variable_entry->var_type = g->builtin_types.entry_invalid;
36113616 } else {
36123617 ZigType *type;
36133618 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
36143619 add_node_error(g, source_node,
36153620 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3616 variable_entry->value->type = g->builtin_types.entry_invalid;
3621 variable_entry->var_type = g->builtin_types.entry_invalid;
36173622 } else {
36183623 Scope *search_scope = nullptr;
36193624 if (src_tld == nullptr) {
......@@ -3627,7 +3632,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
36273632 ErrorMsg *msg = add_node_error(g, source_node,
36283633 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
36293634 add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
3630 variable_entry->value->type = g->builtin_types.entry_invalid;
3635 variable_entry->var_type = g->builtin_types.entry_invalid;
36313636 }
36323637 }
36333638 }
......@@ -3677,7 +3682,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36773682 linkage = VarLinkageInternal;
36783683 }
36793684
3680 IrInstruction *init_value = nullptr;
3685 ConstExprValue *init_value = nullptr;
36813686
36823687 // TODO more validation for types that can't be used for export/extern variables
36833688 ZigType *implicit_type = nullptr;
......@@ -3686,7 +3691,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36863691 } else if (var_decl->expr) {
36873692 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
36883693 assert(init_value);
3689 implicit_type = init_value->value.type;
3694 implicit_type = init_value->type;
36903695
36913696 if (implicit_type->id == ZigTypeIdUnreachable) {
36923697 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
......@@ -3704,7 +3709,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
37043709 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
37053710 implicit_type = g->builtin_types.entry_invalid;
37063711 }
3707 assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);
3712 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
37083713 } else if (linkage != VarLinkageExternal) {
37093714 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
37103715 implicit_type = g->builtin_types.entry_invalid;
......@@ -3713,19 +3718,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
37133718 ZigType *type = explicit_type ? explicit_type : implicit_type;
37143719 assert(type != nullptr); // should have been caught by the parser
37153720
3716 ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);
3721 ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type);
37173722
37183723 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
3719 is_const, init_val, &tld_var->base);
3724 is_const, init_val, &tld_var->base, type);
37203725 tld_var->var->linkage = linkage;
37213726
37223727 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
3723 tld_var->var->value->type = g->builtin_types.entry_invalid;
3728 tld_var->var->var_type = g->builtin_types.entry_invalid;
37243729 }
37253730
37263731 if (var_decl->align_expr != nullptr) {
37273732 if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
3728 tld_var->var->value->type = g->builtin_types.entry_invalid;
3733 tld_var->var->var_type = g->builtin_types.entry_invalid;
37293734 }
37303735 }
37313736
......@@ -4090,7 +4095,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
40904095 }
40914096
40924097 ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
4093 param_name, true, create_const_runtime(param_type), nullptr);
4098 param_name, true, create_const_runtime(param_type), nullptr, param_type);
40944099 var->src_arg_index = i;
40954100 fn_table_entry->child_scope = var->child_scope;
40964101 var->shadowable = var->shadowable || is_var_args;
......@@ -4228,18 +4233,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
42284233 preview_use_decl(g, src_use_node);
42294234 }
42304235
4231 IrInstruction *use_target_value = src_use_node->data.use.value;
4232 if (use_target_value->value.type->id == ZigTypeIdInvalid) {
4236 ConstExprValue *use_target_value = src_use_node->data.use.value;
4237 if (type_is_invalid(use_target_value->type)) {
42334238 dst_use_node->owner->any_imports_failed = true;
42344239 return;
42354240 }
42364241
42374242 dst_use_node->data.use.resolution = TldResolutionOk;
42384243
4239 ConstExprValue *const_val = &use_target_value->value;
4240 assert(const_val->special != ConstValSpecialRuntime);
4244 assert(use_target_value->special != ConstValSpecialRuntime);
42414245
4242 ImportTableEntry *target_import = const_val->data.x_import;
4246 ImportTableEntry *target_import = use_target_value->data.x_import;
42434247 assert(target_import);
42444248
42454249 if (target_import->any_imports_failed) {
......@@ -4302,10 +4306,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
43024306 }
43034307
43044308 node->data.use.resolution = TldResolutionResolving;
4305 IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base,
4309 ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base,
43064310 node->data.use.expr, g->builtin_types.entry_namespace, nullptr);
43074311
4308 if (result->value.type->id == ZigTypeIdInvalid)
4312 if (type_is_invalid(result->type))
43094313 node->owner->any_imports_failed = true;
43104314
43114315 node->data.use.value = result;
......@@ -4486,7 +4490,8 @@ bool handle_is_ptr(ZigType *type_entry) {
44864490 return type_has_bits(type_entry->data.error_union.payload_type);
44874491 case ZigTypeIdOptional:
44884492 return type_has_bits(type_entry->data.maybe.child_type) &&
4489 !type_is_codegen_pointer(type_entry->data.maybe.child_type);
4493 !type_is_codegen_pointer(type_entry->data.maybe.child_type) &&
4494 type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
44904495 case ZigTypeIdUnion:
44914496 assert(type_entry->data.unionation.zero_bits_known);
44924497 if (type_entry->data.unionation.gen_field_count == 0)
......@@ -4732,6 +4737,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
47324737 return true;
47334738}
47344739
4740static uint32_t hash_const_val_error_set(ConstExprValue *const_val) {
4741 assert(const_val->data.x_err_set != nullptr);
4742 return const_val->data.x_err_set->value ^ 2630160122;
4743}
4744
47354745static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
47364746 uint32_t hash_val = 0;
47374747 switch (const_val->data.x_ptr.mut) {
......@@ -4763,6 +4773,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
47634773 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
47644774 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
47654775 return hash_val;
4776 case ConstPtrSpecialBaseErrorUnionCode:
4777 hash_val += (uint32_t)2994743799;
4778 hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val);
4779 return hash_val;
4780 case ConstPtrSpecialBaseErrorUnionPayload:
4781 hash_val += (uint32_t)3456080131;
4782 hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val);
4783 return hash_val;
4784 case ConstPtrSpecialBaseOptionalPayload:
4785 hash_val += (uint32_t)3163140517;
4786 hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val);
4787 return hash_val;
47664788 case ConstPtrSpecialHardCodedAddr:
47674789 hash_val += (uint32_t)4048518294;
47684790 hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);
......@@ -4774,6 +4796,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
47744796 hash_val += (uint32_t)2590901619;
47754797 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
47764798 return hash_val;
4799 case ConstPtrSpecialNull:
4800 hash_val += (uint32_t)1486246455;
4801 return hash_val;
47774802 }
47784803 zig_unreachable();
47794804}
......@@ -4872,7 +4897,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
48724897 return 2709806591;
48734898 case ZigTypeIdOptional:
48744899 if (get_codegen_ptr_type(const_val->type) != nullptr) {
4875 return hash_const_val(const_val) * 1992916303;
4900 return hash_const_val_ptr(const_val) * 1992916303;
4901 } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
4902 return hash_const_val_error_set(const_val) * 3147031929;
48764903 } else {
48774904 if (const_val->data.x_optional) {
48784905 return hash_const_val(const_val->data.x_optional) * 1992916303;
......@@ -4884,8 +4911,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
48844911 // TODO better hashing algorithm
48854912 return 3415065496;
48864913 case ZigTypeIdErrorSet:
4887 assert(const_val->data.x_err_set != nullptr);
4888 return const_val->data.x_err_set->value ^ 2630160122;
4914 return hash_const_val_error_set(const_val);
48894915 case ZigTypeIdNamespace:
48904916 return hash_ptr(const_val->data.x_import);
48914917 case ZigTypeIdBoundFn:
......@@ -4987,7 +5013,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
49875013 return can_mutate_comptime_var_state(value->data.x_optional);
49885014
49895015 case ZigTypeIdErrorUnion:
4990 if (value->data.x_err_union.err != nullptr)
5016 if (value->data.x_err_union.error_set->data.x_err_set != nullptr)
49915017 return false;
49925018 assert(value->data.x_err_union.payload != nullptr);
49935019 return can_mutate_comptime_var_state(value->data.x_err_union.payload);
......@@ -5048,9 +5074,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
50485074 while (scope) {
50495075 if (scope->id == ScopeIdVarDecl) {
50505076 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5051 if (type_is_invalid(var_scope->var->value->type))
5077 if (type_is_invalid(var_scope->var->var_type))
50525078 return false;
5053 if (can_mutate_comptime_var_state(var_scope->var->value))
5079 if (can_mutate_comptime_var_state(var_scope->var->const_value))
50545080 return false;
50555081 } else if (scope->id == ScopeIdFnDef) {
50565082 return true;
......@@ -5068,7 +5094,7 @@ uint32_t fn_eval_hash(Scope* scope) {
50685094 while (scope) {
50695095 if (scope->id == ScopeIdVarDecl) {
50705096 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5071 result += hash_const_val(var_scope->var->value);
5097 result += hash_const_val(var_scope->var->const_value);
50725098 } else if (scope->id == ScopeIdFnDef) {
50735099 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
50745100 result += hash_ptr(fn_scope->fn_entry);
......@@ -5092,10 +5118,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
50925118 if (a->id == ScopeIdVarDecl) {
50935119 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
50945120 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
5095 if (a_var_scope->var->value->type != b_var_scope->var->value->type)
5096 return false;
5097 if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
5121 if (a_var_scope->var->var_type != b_var_scope->var->var_type)
50985122 return false;
5123 if (a_var_scope->var->var_type == a_var_scope->var->const_value->type &&
5124 b_var_scope->var->var_type == b_var_scope->var->const_value->type)
5125 {
5126 if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value))
5127 return false;
5128 } else {
5129 zig_panic("TODO comptime ptr reinterpret for fn_eval_eql");
5130 }
50995131 } else if (a->id == ScopeIdFnDef) {
51005132 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
51015133 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
......@@ -5113,6 +5145,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
51135145 return false;
51145146}
51155147
5148// Whether the type has bits at runtime.
51165149bool type_has_bits(ZigType *type_entry) {
51175150 assert(type_entry);
51185151 assert(!type_is_invalid(type_entry));
......@@ -5120,6 +5153,65 @@ bool type_has_bits(ZigType *type_entry) {
51205153 return !type_entry->zero_bits;
51215154}
51225155
5156// Whether you can infer the value based solely on the type.
5157OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
5158 assert(type_entry != nullptr);
5159 Error err;
5160 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
5161 return OnePossibleValueInvalid;
5162 switch (type_entry->id) {
5163 case ZigTypeIdInvalid:
5164 zig_unreachable();
5165 case ZigTypeIdOpaque:
5166 case ZigTypeIdComptimeFloat:
5167 case ZigTypeIdComptimeInt:
5168 case ZigTypeIdMetaType:
5169 case ZigTypeIdNamespace:
5170 case ZigTypeIdBoundFn:
5171 case ZigTypeIdArgTuple:
5172 case ZigTypeIdOptional:
5173 case ZigTypeIdFn:
5174 case ZigTypeIdBool:
5175 case ZigTypeIdFloat:
5176 case ZigTypeIdPromise:
5177 case ZigTypeIdErrorUnion:
5178 return OnePossibleValueNo;
5179 case ZigTypeIdUndefined:
5180 case ZigTypeIdNull:
5181 case ZigTypeIdVoid:
5182 case ZigTypeIdUnreachable:
5183 return OnePossibleValueYes;
5184 case ZigTypeIdArray:
5185 if (type_entry->data.array.len == 0)
5186 return OnePossibleValueYes;
5187 return type_has_one_possible_value(g, type_entry->data.array.child_type);
5188 case ZigTypeIdStruct:
5189 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
5190 TypeStructField *field = &type_entry->data.structure.fields[i];
5191 switch (type_has_one_possible_value(g, field->type_entry)) {
5192 case OnePossibleValueInvalid:
5193 return OnePossibleValueInvalid;
5194 case OnePossibleValueNo:
5195 return OnePossibleValueNo;
5196 case OnePossibleValueYes:
5197 continue;
5198 }
5199 }
5200 return OnePossibleValueYes;
5201 case ZigTypeIdErrorSet:
5202 case ZigTypeIdEnum:
5203 case ZigTypeIdInt:
5204 return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
5205 case ZigTypeIdPointer:
5206 return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
5207 case ZigTypeIdUnion:
5208 if (type_entry->data.unionation.src_field_count > 1)
5209 return OnePossibleValueNo;
5210 return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);
5211 }
5212 zig_unreachable();
5213}
5214
51235215ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
51245216 Error err;
51255217 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
......@@ -5574,6 +5666,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
55745666 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
55755667 return false;
55765668 return true;
5669 case ConstPtrSpecialBaseErrorUnionCode:
5670 if (a->data.x_ptr.data.base_err_union_code.err_union_val !=
5671 b->data.x_ptr.data.base_err_union_code.err_union_val &&
5672 a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs !=
5673 b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs)
5674 {
5675 return false;
5676 }
5677 return true;
5678 case ConstPtrSpecialBaseErrorUnionPayload:
5679 if (a->data.x_ptr.data.base_err_union_payload.err_union_val !=
5680 b->data.x_ptr.data.base_err_union_payload.err_union_val &&
5681 a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs !=
5682 b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs)
5683 {
5684 return false;
5685 }
5686 return true;
5687 case ConstPtrSpecialBaseOptionalPayload:
5688 if (a->data.x_ptr.data.base_optional_payload.optional_val !=
5689 b->data.x_ptr.data.base_optional_payload.optional_val &&
5690 a->data.x_ptr.data.base_optional_payload.optional_val->global_refs !=
5691 b->data.x_ptr.data.base_optional_payload.optional_val->global_refs)
5692 {
5693 return false;
5694 }
5695 return true;
55775696 case ConstPtrSpecialHardCodedAddr:
55785697 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
55795698 return false;
......@@ -5582,6 +5701,8 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
55825701 return true;
55835702 case ConstPtrSpecialFunction:
55845703 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
5704 case ConstPtrSpecialNull:
5705 return true;
55855706 }
55865707 zig_unreachable();
55875708}
......@@ -5750,7 +5871,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v
57505871 }
57515872}
57525873
5753void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
5874static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
57545875 assert(type_entry->id == ZigTypeIdPointer);
57555876
57565877 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
......@@ -5763,6 +5884,9 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
57635884 zig_unreachable();
57645885 case ConstPtrSpecialRef:
57655886 case ConstPtrSpecialBaseStruct:
5887 case ConstPtrSpecialBaseErrorUnionCode:
5888 case ConstPtrSpecialBaseErrorUnionPayload:
5889 case ConstPtrSpecialBaseOptionalPayload:
57665890 buf_appendf(buf, "*");
57675891 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
57685892 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
......@@ -5790,10 +5914,21 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
57905914 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
57915915 return;
57925916 }
5917 case ConstPtrSpecialNull:
5918 buf_append_str(buf, "null");
5919 return;
57935920 }
57945921 zig_unreachable();
57955922}
57965923
5924static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
5925 if (const_val->data.x_err_set == nullptr) {
5926 buf_append_str(buf, "null");
5927 } else {
5928 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5929 }
5930}
5931
57975932void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
57985933 switch (const_val->special) {
57995934 case ConstValSpecialRuntime:
......@@ -5921,6 +6056,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59216056 {
59226057 if (get_codegen_ptr_type(const_val->type) != nullptr)
59236058 return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
6059 if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet)
6060 return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
59246061 if (const_val->data.x_optional) {
59256062 render_const_value(g, buf, const_val->data.x_optional);
59266063 } else {
......@@ -5958,11 +6095,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59586095 case ZigTypeIdErrorUnion:
59596096 {
59606097 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
5961 if (const_val->data.x_err_union.err == nullptr) {
6098 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6099 if (err_set == nullptr) {
59626100 render_const_value(g, buf, const_val->data.x_err_union.payload);
59636101 } else {
59646102 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
5965 buf_ptr(&const_val->data.x_err_union.err->name));
6103 buf_ptr(&err_set->name));
59666104 }
59676105 buf_appendf(buf, ")");
59686106 return;
......@@ -5977,10 +6115,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59776115 return;
59786116 }
59796117 case ZigTypeIdErrorSet:
5980 {
5981 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5982 return;
5983 }
6118 return render_const_val_err_set(g, buf, const_val, type_entry);
59846119 case ZigTypeIdArgTuple:
59856120 {
59866121 buf_appendf(buf, "(args value)");
......@@ -6172,6 +6307,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
61726307// Canonicalize the array value as ConstArraySpecialNone
61736308void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
61746309 assert(const_val->type->id == ZigTypeIdArray);
6310 if (const_val->special == ConstValSpecialUndef) {
6311 const_val->special = ConstValSpecialStatic;
6312 const_val->data.x_array.special = ConstArraySpecialUndef;
6313 }
61756314 switch (const_val->data.x_array.special) {
61766315 case ConstArraySpecialNone:
61776316 return;
......@@ -6215,17 +6354,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
62156354}
62166355
62176356ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
6218 assert(value->type);
6219 ZigType *type_entry = value->type;
6220 if (type_entry->id == ZigTypeIdArray) {
6221 expand_undef_array(g, value);
6222 return &value->data.x_array.data.s_none.parent;
6223 } else if (type_entry->id == ZigTypeIdStruct) {
6224 return &value->data.x_struct.parent;
6225 } else if (type_entry->id == ZigTypeIdUnion) {
6226 return &value->data.x_union.parent;
6227 }
6228 return nullptr;
6357 return &value->parent;
62296358}
62306359
62316360static const ZigTypeId all_type_ids[] = {
......@@ -6453,7 +6582,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
64536582 resolve_top_level_decl(codegen, tld, false, nullptr);
64546583 assert(tld->id == TldIdVar);
64556584 TldVar *tld_var = (TldVar *)tld;
6456 ConstExprValue *var_value = tld_var->var->value;
6585 ConstExprValue *var_value = tld_var->var->const_value;
64576586 assert(var_value != nullptr);
64586587 return var_value;
64596588}
src/analyze.hpp+8-1
......@@ -81,7 +81,7 @@ ZigFn *scope_fn_entry(Scope *scope);
8181ImportTableEntry *get_scope_import(Scope *scope);
8282void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
8383ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
84 bool is_const, ConstExprValue *init_value, Tld *src_tld);
84 bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type);
8585ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
8686ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
8787ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
......@@ -222,6 +222,13 @@ enum ReqCompTime {
222222};
223223ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
224224
225enum OnePossibleValue {
226 OnePossibleValueInvalid,
227 OnePossibleValueNo,
228 OnePossibleValueYes,
229};
230OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
231
225232Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
226233 ConstExprValue *const_val, ZigType *wanted_type);
227234
src/ast_render.cpp+4-4
......@@ -233,8 +233,8 @@ static const char *node_type_str(NodeType node_type) {
233233 return "ErrorType";
234234 case NodeTypeIfErrorExpr:
235235 return "IfErrorExpr";
236 case NodeTypeTestExpr:
237 return "TestExpr";
236 case NodeTypeIfOptional:
237 return "IfOptional";
238238 case NodeTypeErrorSetDecl:
239239 return "ErrorSetDecl";
240240 case NodeTypeCancel:
......@@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
387387 if (node->data.if_err_expr.else_node)
388388 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
389389 return node->data.if_err_expr.then_node->type == NodeTypeBlock;
390 case NodeTypeTestExpr:
390 case NodeTypeIfOptional:
391391 if (node->data.test_expr.else_node)
392392 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
393393 return node->data.test_expr.then_node->type == NodeTypeBlock;
......@@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
974974 }
975975 break;
976976 }
977 case NodeTypeTestExpr:
977 case NodeTypeIfOptional:
978978 {
979979 fprintf(ar->f, "if (");
980980 render_node_grouped(ar, node->data.test_expr.target_node);
src/codegen.cpp+285-100
......@@ -313,6 +313,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *
313313static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
314314static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
315315static void generate_error_name_table(CodeGen *g);
316static bool value_is_all_undef(ConstExprValue *const_val);
317static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
316318
317319static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
318320 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
......@@ -461,6 +463,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
461463 }
462464}
463465
466static bool cc_want_sret_attr(CallingConvention cc) {
467 switch (cc) {
468 case CallingConventionNaked:
469 zig_unreachable();
470 case CallingConventionC:
471 case CallingConventionCold:
472 case CallingConventionStdcall:
473 return true;
474 case CallingConventionAsync:
475 case CallingConventionUnspecified:
476 return false;
477 }
478 zig_unreachable();
479}
480
464481static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
465482 if (fn_table_entry->llvm_value)
466483 return fn_table_entry->llvm_value;
......@@ -598,9 +615,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
598615 } else if (type_is_codegen_pointer(return_type)) {
599616 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
600617 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
601 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
602618 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
603 if (cc == CallingConventionC) {
619 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
620 if (cc_want_sret_attr(cc)) {
604621 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
605622 }
606623 init_gen_i = 1;
......@@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
22002217 assert(variable);
22012218 assert(variable->value_ref);
22022219
2203 if (!handle_is_ptr(variable->value->type)) {
2220 if (!handle_is_ptr(variable->var_type)) {
22042221 clear_debug_source_node(g);
2205 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,
2206 variable->align_bytes, false);
2222 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
2223 variable->value_ref, variable->align_bytes, false);
22072224 }
22082225
22092226 if (variable->decl_node) {
......@@ -2961,7 +2978,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
29612978}
29622979
29632980static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
2964 IrInstructionPtrCast *instruction)
2981 IrInstructionPtrCastGen *instruction)
29652982{
29662983 ZigType *wanted_type = instruction->base.value.type;
29672984 if (!type_has_bits(wanted_type)) {
......@@ -3149,11 +3166,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
31493166}
31503167
31513168static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3152 IrInstructionDeclVar *decl_var_instruction)
3169 IrInstructionDeclVarGen *decl_var_instruction)
31533170{
31543171 ZigVar *var = decl_var_instruction->var;
31553172
3156 if (!type_has_bits(var->value->type))
3173 if (!type_has_bits(var->var_type))
31573174 return nullptr;
31583175
31593176 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
......@@ -3161,34 +3178,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
31613178
31623179 IrInstruction *init_value = decl_var_instruction->init_value;
31633180
3164 bool have_init_expr = false;
3165
3166 ConstExprValue *const_val = &init_value->value;
3167 if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
3168 have_init_expr = true;
3181 bool have_init_expr = !value_is_all_undef(&init_value->value);
31693182
31703183 if (have_init_expr) {
3171 assert(var->value->type == init_value->value.type);
3172 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
3184 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
31733185 PtrLenSingle, var->align_bytes, 0, 0);
31743186 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
31753187 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3176 } else {
3177 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
3178 if (want_safe) {
3179 ZigType *usize = g->builtin_types.entry_usize;
3180 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref);
3181 assert(size_bytes > 0);
3182
3183 assert(var->align_bytes > 0);
3184
3185 // memset uninitialized memory to 0xa
3186 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3187 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3188 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, "");
3189 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3190 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false);
3191 }
3188 } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
3189 uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
3190 gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
31923191 }
31933192
31943193 gen_var_debug_decl(g, var);
......@@ -3225,21 +3224,75 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
32253224 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
32263225}
32273226
3228static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
3229 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3230 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3227static bool value_is_all_undef(ConstExprValue *const_val) {
3228 switch (const_val->special) {
3229 case ConstValSpecialRuntime:
3230 return false;
3231 case ConstValSpecialUndef:
3232 return true;
3233 case ConstValSpecialStatic:
3234 if (const_val->type->id == ZigTypeIdStruct) {
3235 for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
3236 if (!value_is_all_undef(&const_val->data.x_struct.fields[i]))
3237 return false;
3238 }
3239 return true;
3240 } else if (const_val->type->id == ZigTypeIdArray) {
3241 switch (const_val->data.x_array.special) {
3242 case ConstArraySpecialUndef:
3243 return true;
3244 case ConstArraySpecialBuf:
3245 return false;
3246 case ConstArraySpecialNone:
3247 for (size_t i = 0; i < const_val->type->data.array.len; i += 1) {
3248 if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
3249 return false;
3250 }
3251 return true;
3252 }
3253 zig_unreachable();
3254 } else {
3255 return false;
3256 }
3257 }
3258 zig_unreachable();
3259}
32313260
3232 assert(instruction->ptr->value.type->id == ZigTypeIdPointer);
3233 ZigType *ptr_type = instruction->ptr->value.type;
3261static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
3262 assert(type_has_bits(value_type));
3263 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
3264 assert(size_bytes > 0);
3265 assert(ptr_align_bytes > 0);
3266 // memset uninitialized memory to 0xaa
3267 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3268 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3269 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
3270 ZigType *usize = g->builtin_types.entry_usize;
3271 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3272 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
3273}
32343274
3235 gen_assign_raw(g, ptr, ptr_type, value);
3275static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
3276 ZigType *ptr_type = instruction->ptr->value.type;
3277 assert(ptr_type->id == ZigTypeIdPointer);
3278 if (!type_has_bits(ptr_type))
3279 return nullptr;
32363280
3281 bool have_init_expr = !value_is_all_undef(&instruction->value->value);
3282 if (have_init_expr) {
3283 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3284 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3285 gen_assign_raw(g, ptr, ptr_type, value);
3286 } else if (ir_want_runtime_safety(g, &instruction->base)) {
3287 gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
3288 ir_llvm_value(g, instruction->ptr));
3289 }
32373290 return nullptr;
32383291}
32393292
32403293static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
32413294 ZigVar *var = instruction->var;
3242 if (type_has_bits(var->value->type)) {
3295 if (type_has_bits(var->var_type)) {
32433296 assert(var->value_ref);
32443297 return var->value_ref;
32453298 } else {
......@@ -3553,7 +3606,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
35533606 LLVMPositionBuilderAtEnd(g->builder, ok_block);
35543607 }
35553608
3556 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, "");
3609 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
3610 union_type->data.unionation.gen_union_index, "");
35573611 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
35583612 return bitcasted_union_field_ptr;
35593613}
......@@ -3715,8 +3769,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
37153769 if (child_type->zero_bits) {
37163770 return maybe_handle;
37173771 } else {
3718 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
3719 if (maybe_is_ptr) {
3772 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3773 if (is_scalar) {
37203774 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
37213775 } else {
37223776 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
......@@ -3731,17 +3785,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
37313785 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
37323786}
37333787
3734static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
3735 IrInstructionUnwrapOptional *instruction)
3788static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
3789 IrInstructionOptionalUnwrapPtr *instruction)
37363790{
3737 ZigType *ptr_type = instruction->value->value.type;
3791 ZigType *ptr_type = instruction->base_ptr->value.type;
37383792 assert(ptr_type->id == ZigTypeIdPointer);
37393793 ZigType *maybe_type = ptr_type->data.pointer.child_type;
37403794 assert(maybe_type->id == ZigTypeIdOptional);
37413795 ZigType *child_type = maybe_type->data.maybe.child_type;
3742 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);
3743 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3796 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
37443797 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
3798 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
37453799 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
37463800 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
37473801 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
......@@ -3755,8 +3809,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
37553809 if (child_type->zero_bits) {
37563810 return nullptr;
37573811 } else {
3758 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
3759 if (maybe_is_ptr) {
3812 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3813 if (is_scalar) {
37603814 return maybe_ptr;
37613815 } else {
37623816 LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
......@@ -4174,7 +4228,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)
41744228 zig_unreachable();
41754229}
41764230
4177static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {
4231static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
41784232 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
41794233 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
41804234 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
......@@ -4189,18 +4243,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
41894243 assert(maybe_type->id == ZigTypeIdOptional);
41904244 ZigType *child_type = maybe_type->data.maybe.child_type;
41914245
4192 if (type_is_codegen_pointer(child_type)) {
4246 if (!handle_is_ptr(maybe_type)) {
41934247 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
41944248 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
41954249 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
41964250 }
41974251
41984252 assert(instruction->tmp_ptr != nullptr);
4199 assert(type_has_bits(instruction->type));
4253 assert(type_has_bits(child_type));
42004254
42014255 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
42024256 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
4203 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val);
4257 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
42044258
42054259 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
42064260 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
......@@ -4351,6 +4405,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
43514405 assert(array_type->data.structure.is_slice);
43524406 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
43534407 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
4408 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
43544409
43554410 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
43564411 assert(ptr_index != SIZE_MAX);
......@@ -4540,12 +4595,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
45404595 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
45414596}
45424597
4543static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
4544 ZigType *ptr_type = instruction->value->value.type;
4598static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
4599 IrInstructionUnwrapErrCode *instruction)
4600{
4601 ZigType *ptr_type = instruction->err_union->value.type;
45454602 assert(ptr_type->id == ZigTypeIdPointer);
45464603 ZigType *err_union_type = ptr_type->data.pointer.child_type;
45474604 ZigType *payload_type = err_union_type->data.error_union.payload_type;
4548 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
4605 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);
45494606 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
45504607
45514608 if (type_has_bits(payload_type)) {
......@@ -4556,7 +4613,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
45564613 }
45574614}
45584615
4559static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {
4616static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
4617 IrInstructionUnwrapErrPayload *instruction)
4618{
4619 bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
4620 g->errors_by_index.length > 1;
4621 if (!want_safety && !type_has_bits(instruction->base.value.type))
4622 return nullptr;
45604623 ZigType *ptr_type = instruction->value->value.type;
45614624 assert(ptr_type->id == ZigTypeIdPointer);
45624625 ZigType *err_union_type = ptr_type->data.pointer.child_type;
......@@ -4568,7 +4631,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
45684631 return err_union_handle;
45694632 }
45704633
4571 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {
4634 if (want_safety) {
45724635 LLVMValueRef err_val;
45734636 if (type_has_bits(payload_type)) {
45744637 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
......@@ -4607,7 +4670,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
46074670 }
46084671
46094672 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
4610 if (type_is_codegen_pointer(child_type)) {
4673 if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
46114674 return payload_val;
46124675 }
46134676
......@@ -5184,12 +5247,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
51845247 case IrInstructionIdToBytes:
51855248 case IrInstructionIdEnumToInt:
51865249 case IrInstructionIdCheckRuntimeScope:
5250 case IrInstructionIdDeclVarSrc:
5251 case IrInstructionIdPtrCastSrc:
5252 case IrInstructionIdCmpxchgSrc:
51875253 zig_unreachable();
51885254
5255 case IrInstructionIdDeclVarGen:
5256 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
51895257 case IrInstructionIdReturn:
51905258 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
5191 case IrInstructionIdDeclVar:
5192 return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
51935259 case IrInstructionIdBinOp:
51945260 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
51955261 case IrInstructionIdCast:
......@@ -5220,8 +5286,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52205286 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
52215287 case IrInstructionIdTestNonNull:
52225288 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
5223 case IrInstructionIdUnwrapOptional:
5224 return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);
5289 case IrInstructionIdOptionalUnwrapPtr:
5290 return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
52255291 case IrInstructionIdClz:
52265292 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
52275293 case IrInstructionIdCtz:
......@@ -5236,8 +5302,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52365302 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
52375303 case IrInstructionIdErrName:
52385304 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
5239 case IrInstructionIdCmpxchg:
5240 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);
5305 case IrInstructionIdCmpxchgGen:
5306 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
52415307 case IrInstructionIdFence:
52425308 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
52435309 case IrInstructionIdTruncate:
......@@ -5278,8 +5344,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52785344 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
52795345 case IrInstructionIdUnionInit:
52805346 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
5281 case IrInstructionIdPtrCast:
5282 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);
5347 case IrInstructionIdPtrCastGen:
5348 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
52835349 case IrInstructionIdBitCast:
52845350 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
52855351 case IrInstructionIdWidenOrShorten:
......@@ -5377,6 +5443,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
53775443static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
53785444static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
53795445static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
5446static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
5447static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
5448static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val);
53805449
53815450static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
53825451 switch (parent->id) {
......@@ -5387,6 +5456,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
53875456 case ConstParentIdStruct:
53885457 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
53895458 parent->data.p_struct.field_index);
5459 case ConstParentIdErrUnionCode:
5460 return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val);
5461 case ConstParentIdErrUnionPayload:
5462 return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val);
5463 case ConstParentIdOptionalPayload:
5464 return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val);
53905465 case ConstParentIdArray:
53915466 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
53925467 parent->data.p_array.elem_index);
......@@ -5402,7 +5477,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
54025477
54035478static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
54045479 expand_undef_array(g, array_const_val);
5405 ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;
5480 ConstParent *parent = &array_const_val->parent;
54065481 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
54075482
54085483 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
......@@ -5427,7 +5502,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
54275502}
54285503
54295504static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
5430 ConstParent *parent = &struct_const_val->data.x_struct.parent;
5505 ConstParent *parent = &struct_const_val->parent;
54315506 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
54325507
54335508 ZigType *u32 = g->builtin_types.entry_u32;
......@@ -5438,8 +5513,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
54385513 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
54395514}
54405515
5516static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
5517 ConstParent *parent = &err_union_const_val->parent;
5518 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
5519
5520 ZigType *u32 = g->builtin_types.entry_u32;
5521 LLVMValueRef indices[] = {
5522 LLVMConstNull(u32->type_ref),
5523 LLVMConstInt(u32->type_ref, err_union_err_index, false),
5524 };
5525 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5526}
5527
5528static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
5529 ConstParent *parent = &err_union_const_val->parent;
5530 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
5531
5532 ZigType *u32 = g->builtin_types.entry_u32;
5533 LLVMValueRef indices[] = {
5534 LLVMConstNull(u32->type_ref),
5535 LLVMConstInt(u32->type_ref, err_union_payload_index, false),
5536 };
5537 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5538}
5539
5540static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) {
5541 ConstParent *parent = &optional_const_val->parent;
5542 LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent);
5543
5544 ZigType *u32 = g->builtin_types.entry_u32;
5545 LLVMValueRef indices[] = {
5546 LLVMConstNull(u32->type_ref),
5547 LLVMConstInt(u32->type_ref, maybe_child_index, false),
5548 };
5549 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5550}
5551
54415552static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {
5442 ConstParent *parent = &union_const_val->data.x_union.parent;
5553 ConstParent *parent = &union_const_val->parent;
54435554 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
54445555
54455556 ZigType *u32 = g->builtin_types.entry_u32;
......@@ -5609,6 +5720,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
56095720 render_const_val_global(g, const_val, "");
56105721 return ptr_val;
56115722 }
5723 case ConstPtrSpecialBaseErrorUnionCode:
5724 {
5725 render_const_val_global(g, const_val, name);
5726 ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
5727 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
5728 if (err_union_const_val->type->zero_bits) {
5729 // make this a null pointer
5730 ZigType *usize = g->builtin_types.entry_usize;
5731 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5732 const_val->type->type_ref);
5733 render_const_val_global(g, const_val, "");
5734 return const_val->global_refs->llvm_value;
5735 }
5736 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val);
5737 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5738 const_val->global_refs->llvm_value = ptr_val;
5739 render_const_val_global(g, const_val, "");
5740 return ptr_val;
5741 }
5742 case ConstPtrSpecialBaseErrorUnionPayload:
5743 {
5744 render_const_val_global(g, const_val, name);
5745 ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
5746 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
5747 if (err_union_const_val->type->zero_bits) {
5748 // make this a null pointer
5749 ZigType *usize = g->builtin_types.entry_usize;
5750 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5751 const_val->type->type_ref);
5752 render_const_val_global(g, const_val, "");
5753 return const_val->global_refs->llvm_value;
5754 }
5755 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val);
5756 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5757 const_val->global_refs->llvm_value = ptr_val;
5758 render_const_val_global(g, const_val, "");
5759 return ptr_val;
5760 }
5761 case ConstPtrSpecialBaseOptionalPayload:
5762 {
5763 render_const_val_global(g, const_val, name);
5764 ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
5765 assert(optional_const_val->type->id == ZigTypeIdOptional);
5766 if (optional_const_val->type->zero_bits) {
5767 // make this a null pointer
5768 ZigType *usize = g->builtin_types.entry_usize;
5769 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5770 const_val->type->type_ref);
5771 render_const_val_global(g, const_val, "");
5772 return const_val->global_refs->llvm_value;
5773 }
5774 LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val);
5775 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5776 const_val->global_refs->llvm_value = ptr_val;
5777 render_const_val_global(g, const_val, "");
5778 return ptr_val;
5779 }
56125780 case ConstPtrSpecialHardCodedAddr:
56135781 {
56145782 render_const_val_global(g, const_val, name);
......@@ -5621,10 +5789,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
56215789 }
56225790 case ConstPtrSpecialFunction:
56235791 return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
5792 case ConstPtrSpecialNull:
5793 return LLVMConstNull(const_val->type->type_ref);
56245794 }
56255795 zig_unreachable();
56265796}
56275797
5798static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) {
5799 uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value;
5800 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false);
5801}
5802
56285803static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
56295804 Error err;
56305805
......@@ -5644,9 +5819,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
56445819 case ZigTypeIdInt:
56455820 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
56465821 case ZigTypeIdErrorSet:
5647 assert(const_val->data.x_err_set != nullptr);
5648 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
5649 const_val->data.x_err_set->value, false);
5822 return gen_const_val_err_set(g, const_val, name);
56505823 case ZigTypeIdFloat:
56515824 switch (type_entry->data.floating.bit_count) {
56525825 case 16:
......@@ -5680,6 +5853,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
56805853 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
56815854 } else if (type_is_codegen_pointer(child_type)) {
56825855 return gen_const_val_ptr(g, const_val, name);
5856 } else if (child_type->id == ZigTypeIdErrorSet) {
5857 return gen_const_val_err_set(g, const_val, name);
56835858 } else {
56845859 LLVMValueRef child_val;
56855860 LLVMValueRef maybe_val;
......@@ -5914,7 +6089,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
59146089 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
59156090 if (!type_has_bits(payload_type)) {
59166091 assert(type_has_bits(err_set_type));
5917 uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;
6092 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6093 uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
59186094 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
59196095 } else if (!type_has_bits(err_set_type)) {
59206096 assert(type_has_bits(payload_type));
......@@ -5923,8 +6099,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
59236099 LLVMValueRef err_tag_value;
59246100 LLVMValueRef err_payload_value;
59256101 bool make_unnamed_struct;
5926 if (const_val->data.x_err_union.err) {
5927 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
6102 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6103 if (err_set != nullptr) {
6104 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
59286105 err_payload_value = LLVMConstNull(payload_type->type_ref);
59296106 make_unnamed_struct = false;
59306107 } else {
......@@ -6130,10 +6307,13 @@ static void do_code_gen(CodeGen *g) {
61306307 TldVar *tld_var = g->global_vars.at(i);
61316308 ZigVar *var = tld_var->var;
61326309
6133 if (var->value->type->id == ZigTypeIdComptimeFloat) {
6310 if (var->var_type->id == ZigTypeIdComptimeFloat) {
61346311 // Generate debug info for it but that's it.
6135 ConstExprValue *const_val = var->value;
6312 ConstExprValue *const_val = var->const_value;
61366313 assert(const_val->special != ConstValSpecialRuntime);
6314 if (const_val->type != var->var_type) {
6315 zig_panic("TODO debug info for var with ptr casted value");
6316 }
61376317 ZigType *var_type = g->builtin_types.entry_f128;
61386318 ConstExprValue coerced_value;
61396319 coerced_value.special = ConstValSpecialStatic;
......@@ -6144,10 +6324,13 @@ static void do_code_gen(CodeGen *g) {
61446324 continue;
61456325 }
61466326
6147 if (var->value->type->id == ZigTypeIdComptimeInt) {
6327 if (var->var_type->id == ZigTypeIdComptimeInt) {
61486328 // Generate debug info for it but that's it.
6149 ConstExprValue *const_val = var->value;
6329 ConstExprValue *const_val = var->const_value;
61506330 assert(const_val->special != ConstValSpecialRuntime);
6331 if (const_val->type != var->var_type) {
6332 zig_panic("TODO debug info for var with ptr casted value");
6333 }
61516334 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
61526335 if (bits_needed < 8) {
61536336 bits_needed = 8;
......@@ -6158,7 +6341,7 @@ static void do_code_gen(CodeGen *g) {
61586341 continue;
61596342 }
61606343
6161 if (!type_has_bits(var->value->type))
6344 if (!type_has_bits(var->var_type))
61626345 continue;
61636346
61646347 assert(var->decl_node);
......@@ -6167,9 +6350,9 @@ static void do_code_gen(CodeGen *g) {
61676350 if (var->linkage == VarLinkageExternal) {
61686351 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
61696352 if (existing_llvm_var) {
6170 global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0));
6353 global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0));
61716354 } else {
6172 global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name));
6355 global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
61736356 // TODO debug info for the extern variable
61746357
61756358 LLVMSetLinkage(global_value, LLVMExternalLinkage);
......@@ -6180,9 +6363,9 @@ static void do_code_gen(CodeGen *g) {
61806363 } else {
61816364 bool exported = (var->linkage == VarLinkageExport);
61826365 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
6183 render_const_val(g, var->value, mangled_name);
6184 render_const_val_global(g, var->value, mangled_name);
6185 global_value = var->value->global_refs->llvm_global;
6366 render_const_val(g, var->const_value, mangled_name);
6367 render_const_val_global(g, var->const_value, mangled_name);
6368 global_value = var->const_value->global_refs->llvm_global;
61866369
61876370 if (exported) {
61886371 LLVMSetLinkage(global_value, LLVMExternalLinkage);
......@@ -6194,8 +6377,10 @@ static void do_code_gen(CodeGen *g) {
61946377 LLVMSetAlignment(global_value, var->align_bytes);
61956378
61966379 // TODO debug info for function pointers
6197 if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {
6198 gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);
6380 // Here we use const_value->type because that's the type of the llvm global,
6381 // which we const ptr cast upon use to whatever it needs to be.
6382 if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) {
6383 gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type);
61996384 }
62006385
62016386 LLVMSetGlobalConstant(global_value, var->gen_is_const);
......@@ -6281,8 +6466,8 @@ static void do_code_gen(CodeGen *g) {
62816466 } else if (instruction->id == IrInstructionIdErrWrapCode) {
62826467 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
62836468 slot = &err_wrap_code_instruction->tmp_ptr;
6284 } else if (instruction->id == IrInstructionIdCmpxchg) {
6285 IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;
6469 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
6470 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
62866471 slot = &cmpxchg_instruction->tmp_ptr;
62876472 } else {
62886473 zig_unreachable();
......@@ -6304,12 +6489,12 @@ static void do_code_gen(CodeGen *g) {
63046489 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
63056490 ZigVar *var = fn_table_entry->variable_list.at(var_i);
63066491
6307 if (!type_has_bits(var->value->type)) {
6492 if (!type_has_bits(var->var_type)) {
63086493 continue;
63096494 }
63106495 if (ir_get_var_is_comptime(var))
63116496 continue;
6312 switch (type_requires_comptime(g, var->value->type)) {
6497 switch (type_requires_comptime(g, var->var_type)) {
63136498 case ReqCompTimeInvalid:
63146499 zig_unreachable();
63156500 case ReqCompTimeYes:
......@@ -6319,11 +6504,11 @@ static void do_code_gen(CodeGen *g) {
63196504 }
63206505
63216506 if (var->src_arg_index == SIZE_MAX) {
6322 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
6507 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
63236508
63246509 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
63256510 buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),
6326 var->value->type->di_type, !g->strip_debug_symbols, 0);
6511 var->var_type->di_type, !g->strip_debug_symbols, 0);
63276512
63286513 } else if (is_c_abi) {
63296514 fn_walk_var.data.vars.var = var;
......@@ -6333,16 +6518,16 @@ static void do_code_gen(CodeGen *g) {
63336518 ZigType *gen_type;
63346519 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
63356520
6336 if (handle_is_ptr(var->value->type)) {
6521 if (handle_is_ptr(var->var_type)) {
63376522 if (gen_info->is_byval) {
6338 gen_type = var->value->type;
6523 gen_type = var->var_type;
63396524 } else {
63406525 gen_type = gen_info->type;
63416526 }
63426527 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
63436528 } else {
6344 gen_type = var->value->type;
6345 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
6529 gen_type = var->var_type;
6530 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
63466531 }
63476532 if (var->decl_node) {
63486533 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
......@@ -7458,9 +7643,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
74587643 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
74597644 this_val->special = ConstValSpecialStatic;
74607645 this_val->type = struct_type;
7461 this_val->data.x_struct.parent.id = ConstParentIdArray;
7462 this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;
7463 this_val->data.x_struct.parent.data.p_array.elem_index = i;
7646 this_val->parent.id = ConstParentIdArray;
7647 this_val->parent.data.p_array.array_val = test_fn_array;
7648 this_val->parent.data.p_array.elem_index = i;
74647649 this_val->data.x_struct.fields = create_const_vals(2);
74657650
74667651 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
src/ir.cpp+827-644
......@@ -167,6 +167,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
167167 ZigType *dest_type, IrInstruction *dest_type_src);
168168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
170171
171172static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
172173 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -178,15 +179,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
178179 case ConstPtrSpecialRef:
179180 result = const_val->data.x_ptr.data.ref.pointee;
180181 break;
181 case ConstPtrSpecialBaseArray:
182 expand_undef_array(g, const_val->data.x_ptr.data.base_array.array_val);
183 result = &const_val->data.x_ptr.data.base_array.array_val->data.x_array.data.s_none.elements[
184 const_val->data.x_ptr.data.base_array.elem_index];
182 case ConstPtrSpecialBaseArray: {
183 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
184 expand_undef_array(g, array_val);
185 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
185186 break;
187 }
186188 case ConstPtrSpecialBaseStruct:
187189 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
188190 const_val->data.x_ptr.data.base_struct.field_index];
189191 break;
192 case ConstPtrSpecialBaseErrorUnionCode:
193 result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
194 break;
195 case ConstPtrSpecialBaseErrorUnionPayload:
196 result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload;
197 break;
198 case ConstPtrSpecialBaseOptionalPayload:
199 result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional;
200 break;
201 case ConstPtrSpecialNull:
202 result = const_val;
203 break;
190204 case ConstPtrSpecialHardCodedAddr:
191205 zig_unreachable();
192206 case ConstPtrSpecialDiscard:
......@@ -198,6 +212,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
198212 return result;
199213}
200214
215static bool is_opt_err_set(ZigType *ty) {
216 return ty->id == ZigTypeIdErrorSet ||
217 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
218}
219
201220static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
202221 if (a == b)
203222 return true;
......@@ -208,15 +227,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
208227 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
209228 return true;
210229
211 return false;
212}
230 if (is_opt_err_set(a) && is_opt_err_set(b))
231 return true;
213232
214ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
215 ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val);
216 if (const_val->type->id == ZigTypeIdPointer) {
217 assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type));
218 }
219 return result;
233 return false;
220234}
221235
222236static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
......@@ -305,6 +319,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
305319 return new_bb;
306320}
307321
322static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) {
323 return IrInstructionIdDeclVarSrc;
324}
325
326static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) {
327 return IrInstructionIdDeclVarGen;
328}
329
308330static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
309331 return IrInstructionIdCondBr;
310332}
......@@ -337,10 +359,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
337359 return IrInstructionIdBinOp;
338360}
339361
340static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
341 return IrInstructionIdDeclVar;
342}
343
344362static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {
345363 return IrInstructionIdExport;
346364}
......@@ -449,8 +467,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {
449467 return IrInstructionIdTestNonNull;
450468}
451469
452static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) {
453 return IrInstructionIdUnwrapOptional;
470static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) {
471 return IrInstructionIdOptionalUnwrapPtr;
454472}
455473
456474static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
......@@ -517,8 +535,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
517535 return IrInstructionIdEmbedFile;
518536}
519537
520static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) {
521 return IrInstructionIdCmpxchg;
538static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) {
539 return IrInstructionIdCmpxchgSrc;
540}
541
542static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) {
543 return IrInstructionIdCmpxchgGen;
522544}
523545
524546static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {
......@@ -649,8 +671,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
649671 return IrInstructionIdTestComptime;
650672}
651673
652static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {
653 return IrInstructionIdPtrCast;
674static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) {
675 return IrInstructionIdPtrCastSrc;
676}
677
678static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
679 return IrInstructionIdPtrCastGen;
654680}
655681
656682static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
......@@ -915,7 +941,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
915941 ir_ref_instruction(condition, irb->current_basic_block);
916942 ir_ref_bb(then_block);
917943 ir_ref_bb(else_block);
918 if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block);
944 if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block);
919945
920946 return &cond_br_instruction->base;
921947}
......@@ -931,16 +957,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
931957 return &return_instruction->base;
932958}
933959
934static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node,
935 ZigType *type_entry)
936{
937 assert(type_entry);
938 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node);
939 const_instruction->base.value.type = type_entry;
940 const_instruction->base.value.special = ConstValSpecialStatic;
941 return &const_instruction->base;
942}
943
944960static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
945961 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
946962 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
......@@ -1188,14 +1204,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
11881204 call_instruction->async_allocator = async_allocator;
11891205 call_instruction->new_stack = new_stack;
11901206
1191 if (fn_ref)
1192 ir_ref_instruction(fn_ref, irb->current_basic_block);
1207 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
11931208 for (size_t i = 0; i < arg_count; i += 1)
11941209 ir_ref_instruction(args[i], irb->current_basic_block);
1195 if (async_allocator)
1196 ir_ref_instruction(async_allocator, irb->current_basic_block);
1197 if (new_stack != nullptr)
1198 ir_ref_instruction(new_stack, irb->current_basic_block);
1210 if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block);
1211 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
11991212
12001213 return &call_instruction->base;
12011214}
......@@ -1280,7 +1293,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
12801293 container_init_list_instruction->item_count = item_count;
12811294 container_init_list_instruction->items = items;
12821295
1283 ir_ref_instruction(container_type, irb->current_basic_block);
1296 if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
12841297 for (size_t i = 0; i < item_count; i += 1) {
12851298 ir_ref_instruction(items[i], irb->current_basic_block);
12861299 }
......@@ -1355,10 +1368,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
13551368 return &instruction->base;
13561369}
13571370
1358static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,
1371static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
13591372 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
13601373{
1361 IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node);
1374 IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node);
13621375 decl_var_instruction->base.value.special = ConstValSpecialStatic;
13631376 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
13641377 decl_var_instruction->var = var;
......@@ -1366,13 +1379,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s
13661379 decl_var_instruction->align_value = align_value;
13671380 decl_var_instruction->init_value = init_value;
13681381
1369 if (var_type) ir_ref_instruction(var_type, irb->current_basic_block);
1370 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
1382 if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
1383 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
13711384 ir_ref_instruction(init_value, irb->current_basic_block);
13721385
13731386 return &decl_var_instruction->base;
13741387}
13751388
1389static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1390 ZigVar *var, IrInstruction *init_value)
1391{
1392 IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb,
1393 source_instruction->scope, source_instruction->source_node);
1394 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1395 decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;
1396 decl_var_instruction->var = var;
1397 decl_var_instruction->init_value = init_value;
1398
1399 ir_ref_instruction(init_value, ira->new_irb.current_basic_block);
1400
1401 return &decl_var_instruction->base;
1402}
1403
13761404static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
13771405 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
13781406{
......@@ -1542,14 +1570,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
15421570 return &instruction->base;
15431571}
15441572
1545static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,
1546 bool safety_check_on)
1573static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1574 IrInstruction *base_ptr, bool safety_check_on)
15471575{
1548 IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node);
1549 instruction->value = value;
1576 IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);
1577 instruction->base_ptr = base_ptr;
15501578 instruction->safety_check_on = safety_check_on;
15511579
1552 ir_ref_instruction(value, irb->current_basic_block);
1580 ir_ref_instruction(base_ptr, irb->current_basic_block);
15531581
15541582 return &instruction->base;
15551583}
......@@ -1765,13 +1793,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
17651793 return &instruction->base;
17661794}
17671795
1768static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value,
1769 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1796static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1797 IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
17701798 IrInstruction *success_order_value, IrInstruction *failure_order_value,
1771 bool is_weak,
1772 ZigType *type, AtomicOrder success_order, AtomicOrder failure_order)
1799 bool is_weak)
17731800{
1774 IrInstructionCmpxchg *instruction = ir_build_instruction<IrInstructionCmpxchg>(irb, scope, source_node);
1801 IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
17751802 instruction->type_value = type_value;
17761803 instruction->ptr = ptr;
17771804 instruction->cmp_value = cmp_value;
......@@ -1779,16 +1806,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so
17791806 instruction->success_order_value = success_order_value;
17801807 instruction->failure_order_value = failure_order_value;
17811808 instruction->is_weak = is_weak;
1782 instruction->type = type;
1783 instruction->success_order = success_order;
1784 instruction->failure_order = failure_order;
17851809
1786 if (type_value != nullptr) ir_ref_instruction(type_value, irb->current_basic_block);
1810 ir_ref_instruction(type_value, irb->current_basic_block);
17871811 ir_ref_instruction(ptr, irb->current_basic_block);
17881812 ir_ref_instruction(cmp_value, irb->current_basic_block);
17891813 ir_ref_instruction(new_value, irb->current_basic_block);
1790 if (type_value != nullptr) ir_ref_instruction(success_order_value, irb->current_basic_block);
1791 if (type_value != nullptr) ir_ref_instruction(failure_order_value, irb->current_basic_block);
1814 ir_ref_instruction(success_order_value, irb->current_basic_block);
1815 ir_ref_instruction(failure_order_value, irb->current_basic_block);
1816
1817 return &instruction->base;
1818}
1819
1820static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1821 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1822 AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)
1823{
1824 IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb,
1825 source_instruction->scope, source_instruction->source_node);
1826 instruction->ptr = ptr;
1827 instruction->cmp_value = cmp_value;
1828 instruction->new_value = new_value;
1829 instruction->success_order = success_order;
1830 instruction->failure_order = failure_order;
1831 instruction->is_weak = is_weak;
1832
1833 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
1834 ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
1835 ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
17921836
17931837 return &instruction->base;
17941838}
......@@ -2060,12 +2104,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
20602104}
20612105
20622106static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
2063 IrInstruction *value)
2107 IrInstruction *err_union)
20642108{
20652109 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);
2066 instruction->value = value;
2110 instruction->err_union = err_union;
20672111
2068 ir_ref_instruction(value, irb->current_basic_block);
2112 ir_ref_instruction(err_union, irb->current_basic_block);
20692113
20702114 return &instruction->base;
20712115}
......@@ -2115,20 +2159,33 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
21152159 return &instruction->base;
21162160}
21172161
2118static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
2162static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
21192163 IrInstruction *dest_type, IrInstruction *ptr)
21202164{
2121 IrInstructionPtrCast *instruction = ir_build_instruction<IrInstructionPtrCast>(
2165 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
21222166 irb, scope, source_node);
21232167 instruction->dest_type = dest_type;
21242168 instruction->ptr = ptr;
21252169
2126 if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);
2170 ir_ref_instruction(dest_type, irb->current_basic_block);
21272171 ir_ref_instruction(ptr, irb->current_basic_block);
21282172
21292173 return &instruction->base;
21302174}
21312175
2176static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
2177 ZigType *ptr_type, IrInstruction *ptr)
2178{
2179 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
2180 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2181 instruction->base.value.type = ptr_type;
2182 instruction->ptr = ptr;
2183
2184 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
2185
2186 return &instruction->base;
2187}
2188
21322189static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
21332190 IrInstruction *dest_type, IrInstruction *value)
21342191{
......@@ -2807,10 +2864,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
28072864 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
28082865 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
28092866 if (defer_expr_value != irb->codegen->invalid_instruction) {
2810 if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == ZigTypeIdUnreachable) {
2867 if (defer_expr_value->value.type != nullptr &&
2868 defer_expr_value->value.type->id == ZigTypeIdUnreachable)
2869 {
28112870 is_noreturn = true;
28122871 } else {
2813 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));
2872 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
2873 defer_expr_value));
28142874 }
28152875 }
28162876 }
......@@ -3065,7 +3125,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
30653125 variable_entry->mem_slot_index = SIZE_MAX;
30663126 variable_entry->is_comptime = is_comptime;
30673127 variable_entry->src_arg_index = SIZE_MAX;
3068 variable_entry->value = create_const_vals(1);
3128 variable_entry->const_value = create_const_vals(1);
30693129
30703130 if (is_comptime != nullptr) {
30713131 is_comptime->ref_count += 1;
......@@ -3080,20 +3140,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
30803140 ErrorMsg *msg = add_node_error(codegen, node,
30813141 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
30823142 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3083 variable_entry->value->type = codegen->builtin_types.entry_invalid;
3143 variable_entry->var_type = codegen->builtin_types.entry_invalid;
30843144 } else {
30853145 ZigType *type;
30863146 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
30873147 add_node_error(codegen, node,
30883148 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3089 variable_entry->value->type = codegen->builtin_types.entry_invalid;
3149 variable_entry->var_type = codegen->builtin_types.entry_invalid;
30903150 } else {
30913151 Tld *tld = find_decl(codegen, parent_scope, name);
30923152 if (tld != nullptr) {
30933153 ErrorMsg *msg = add_node_error(codegen, node,
30943154 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
30953155 add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));
3096 variable_entry->value->type = codegen->builtin_types.entry_invalid;
3156 variable_entry->var_type = codegen->builtin_types.entry_invalid;
30973157 }
30983158 }
30993159 }
......@@ -3156,7 +3216,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
31563216 scope_block->incoming_blocks = &incoming_blocks;
31573217 scope_block->incoming_values = &incoming_values;
31583218 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
3159 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope));
3219 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
3220 ir_should_inline(irb->exec, parent_scope));
31603221 }
31613222
31623223 bool is_continuation_unreachable = false;
......@@ -3174,9 +3235,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
31743235 // defer starts a new scope
31753236 child_scope = statement_node->data.defer.child_scope;
31763237 assert(child_scope);
3177 } else if (statement_value->id == IrInstructionIdDeclVar) {
3238 } else if (statement_value->id == IrInstructionIdDeclVarSrc) {
31783239 // variable declarations start a new scope
3179 IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;
3240 IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value;
31803241 child_scope = decl_var_instruction->var->child_scope;
31813242 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {
31823243 // this statement's value must be void
......@@ -3331,7 +3392,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
33313392 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
33323393}
33333394
3334static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
3395static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
33353396 assert(node->type == NodeTypeBinOpExpr);
33363397
33373398 AstNode *op1_node = node->data.bin_op_expr.op1;
......@@ -3365,7 +3426,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
33653426 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
33663427
33673428 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3368 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);
3429 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false);
33693430 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
33703431 IrBasicBlock *after_ok_block = irb->current_basic_block;
33713432 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
......@@ -3483,7 +3544,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
34833544 case BinOpTypeMergeErrorSets:
34843545 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
34853546 case BinOpTypeUnwrapOptional:
3486 return ir_gen_maybe_ok_or(irb, scope, node);
3547 return ir_gen_orelse(irb, scope, node);
34873548 case BinOpTypeErrorUnion:
34883549 return ir_gen_error_union(irb, scope, node);
34893550 }
......@@ -3542,6 +3603,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
35423603 buf_ptr(variable_name)));
35433604 return irb->codegen->invalid_instruction;
35443605 }
3606 assert(err == ErrorPrimitiveTypeNotFound);
35453607 } else {
35463608 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
35473609 if (lval == LValPtr) {
......@@ -3904,9 +3966,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
39043966 if (arg5_value == irb->codegen->invalid_instruction)
39053967 return arg5_value;
39063968
3907 IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value,
3908 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
3909 nullptr, AtomicOrderUnordered, AtomicOrderUnordered);
3969 IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
3970 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
39103971 return ir_lval_wrap(irb, scope, cmpxchg, lval);
39113972 }
39123973 case BuiltinFnIdFence:
......@@ -4346,7 +4407,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
43464407 if (arg1_value == irb->codegen->invalid_instruction)
43474408 return arg1_value;
43484409
4349 IrInstruction *ptr_cast = ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value);
4410 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value);
43504411 return ir_lval_wrap(irb, scope, ptr_cast, lval);
43514412 }
43524413 case BuiltinFnIdBitCast:
......@@ -4784,7 +4845,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
47844845 }
47854846 }
47864847
4787 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr);
4848 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
4849 is_async, async_allocator, nullptr);
47884850 return ir_lval_wrap(irb, scope, fn_call, lval);
47894851}
47904852
......@@ -4793,7 +4855,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
47934855
47944856 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
47954857 if (condition == irb->codegen->invalid_instruction)
4796 return condition;
4858 return irb->codegen->invalid_instruction;
47974859
47984860 IrInstruction *is_comptime;
47994861 if (ir_should_inline(irb->exec, scope)) {
......@@ -4816,7 +4878,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
48164878 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
48174879 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
48184880 if (then_expr_result == irb->codegen->invalid_instruction)
4819 return then_expr_result;
4881 return irb->codegen->invalid_instruction;
48204882 IrBasicBlock *after_then_block = irb->current_basic_block;
48214883 if (!instr_is_unreachable(then_expr_result))
48224884 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
......@@ -4826,7 +4888,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
48264888 if (else_node) {
48274889 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
48284890 if (else_expr_result == irb->codegen->invalid_instruction)
4829 return else_expr_result;
4891 return irb->codegen->invalid_instruction;
48304892 } else {
48314893 else_expr_result = ir_build_const_void(irb, scope, node);
48324894 }
......@@ -4927,7 +4989,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
49274989 ptr_len, align_value, bit_offset_start, host_int_bytes);
49284990}
49294991
4930static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
4992static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
49314993 LVal lval)
49324994{
49334995 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
......@@ -5053,11 +5115,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
50535115 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
50545116 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
50555117 is_const, is_const, is_shadowable, is_comptime);
5056 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node
5118 // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
50575119 // is inside var->child_scope
50585120
50595121 if (!is_extern && !variable_declaration->expr) {
5060 var->value->type = irb->codegen->builtin_types.entry_invalid;
5122 var->var_type = irb->codegen->builtin_types.entry_invalid;
50615123 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));
50625124 return irb->codegen->invalid_instruction;
50635125 }
......@@ -5084,7 +5146,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
50845146 if (init_value == irb->codegen->invalid_instruction)
50855147 return init_value;
50865148
5087 return ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value);
5149 return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value);
50885150}
50895151
50905152static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
......@@ -5140,7 +5202,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
51405202 err_val_ptr, false);
51415203 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
51425204 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
5143 ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
5205 ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
51445206 }
51455207
51465208 ZigList<IrInstruction *> incoming_values = {0};
......@@ -5180,7 +5242,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
51805242 true, false, false, is_comptime);
51815243 Scope *err_scope = err_var->child_scope;
51825244 IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
5183 ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
5245 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
51845246
51855247 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
51865248 if (else_result == irb->codegen->invalid_instruction)
......@@ -5220,10 +5282,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
52205282 }
52215283
52225284 ir_set_cursor_at_end_and_append_block(irb, body_block);
5223 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false);
5285 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
52245286 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
52255287 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
5226 ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
5288 ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
52275289
52285290 ZigList<IrInstruction *> incoming_values = {0};
52295291 ZigList<IrBasicBlock *> incoming_blocks = {0};
......@@ -5380,7 +5442,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
53805442 Scope *child_scope = elem_var->child_scope;
53815443
53825444 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
5383 ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
5445 ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
53845446 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
53855447
53865448 AstNode *index_var_source_node;
......@@ -5398,7 +5460,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
53985460 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
53995461 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
54005462 IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);
5401 ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
5463 ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
54025464 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);
54035465
54045466
......@@ -5622,8 +5684,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
56225684 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
56235685}
56245686
5625static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5626 assert(node->type == NodeTypeTestExpr);
5687static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5688 assert(node->type == NodeTypeIfOptional);
56275689
56285690 Buf *var_symbol = node->data.test_expr.var_symbol;
56295691 AstNode *expr_node = node->data.test_expr.target_node;
......@@ -5661,9 +5723,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
56615723 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
56625724 var_symbol, is_const, is_const, is_shadowable, is_comptime);
56635725
5664 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false);
5726 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);
56655727 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
5666 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5728 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
56675729 var_scope = var->child_scope;
56685730 } else {
56695731 var_scope = subexpr_scope;
......@@ -5738,7 +5800,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
57385800
57395801 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
57405802 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
5741 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5803 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
57425804 var_scope = var->child_scope;
57435805 } else {
57445806 var_scope = subexpr_scope;
......@@ -5763,7 +5825,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
57635825 err_symbol, is_const, is_const, is_shadowable, is_comptime);
57645826
57655827 IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
5766 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5828 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
57675829 err_var_scope = var->child_scope;
57685830 } else {
57695831 err_var_scope = subexpr_scope;
......@@ -5818,7 +5880,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
58185880 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);
58195881 }
58205882 IrInstruction *var_type = nullptr; // infer the type
5821 ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
5883 ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
58225884 } else {
58235885 child_scope = scope;
58245886 }
......@@ -6228,7 +6290,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
62286290 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
62296291}
62306292
6231static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
6293static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
62326294 assert(node->type == NodeTypeUnwrapErrorExpr);
62336295
62346296 AstNode *op1_node = node->data.unwrap_err_expr.op1;
......@@ -6242,7 +6304,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
62426304 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
62436305 return irb->codegen->invalid_instruction;
62446306 }
6245 return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LValNone);
6307 return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone);
62466308 }
62476309
62486310
......@@ -6276,7 +6338,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
62766338 is_const, is_const, is_shadowable, is_comptime);
62776339 err_scope = var->child_scope;
62786340 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
6279 ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
6341 ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
62806342 } else {
62816343 err_scope = parent_scope;
62826344 }
......@@ -6312,7 +6374,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
63126374 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;
63136375 if (need_comma)
63146376 buf_append_char(name, ',');
6315 render_const_value(codegen, name, var_scope->var->value);
6377 // TODO: const ptr reinterpret here to make the var type agree with the value?
6378 render_const_value(codegen, name, var_scope->var->const_value);
63166379 return true;
63176380}
63186381
......@@ -6562,7 +6625,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
65626625 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
65636626
65646627 // TODO relies on Zig not re-ordering fields
6565 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);
6628 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
65666629 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
65676630 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
65686631 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
......@@ -6640,7 +6703,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
66406703 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
66416704
66426705 // TODO relies on Zig not re-ordering fields
6643 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);
6706 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
66446707 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
66456708 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
66466709 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
......@@ -6756,7 +6819,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
67566819 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
67576820 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
67586821 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
6759 ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
6822 ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
67606823 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
67616824 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
67626825 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
......@@ -7050,7 +7113,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
70507113 if (maybe_ptr == irb->codegen->invalid_instruction)
70517114 return irb->codegen->invalid_instruction;
70527115
7053 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true);
7116 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true);
70547117 if (lval == LValPtr)
70557118 return unwrapped_ptr;
70567119
......@@ -7074,8 +7137,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
70747137 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
70757138 case NodeTypeIfErrorExpr:
70767139 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
7077 case NodeTypeTestExpr:
7078 return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);
7140 case NodeTypeIfOptional:
7141 return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
70797142 case NodeTypeSwitchExpr:
70807143 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
70817144 case NodeTypeCompTime:
......@@ -7093,7 +7156,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
70937156 case NodeTypeSliceExpr:
70947157 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
70957158 case NodeTypeUnwrapErrorExpr:
7096 return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);
7159 return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval);
70977160 case NodeTypeContainerDecl:
70987161 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
70997162 case NodeTypeFnProto:
......@@ -7152,6 +7215,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
71527215 ir_ref_bb(irb->current_basic_block);
71537216
71547217 ZigFn *fn_entry = exec_fn_entry(irb->exec);
7218
71557219 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
71567220 IrInstruction *coro_id;
71577221 IrInstruction *u8_ptr_type;
......@@ -7172,27 +7236,27 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
71727236 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
71737237 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
71747238 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
7175 ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
7239 ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
71767240 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
71777241
71787242 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
71797243 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
71807244 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
71817245 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
7182 ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
7246 ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
71837247 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
71847248
71857249 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
71867250 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
7187 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
7251 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
71887252 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
71897253 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
71907254 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
7191 ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
7255 ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
71927256 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
71937257 ImplicitAllocatorIdArg);
71947258 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
7195 ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
7259 ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
71967260 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
71977261 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
71987262 IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);
......@@ -7208,7 +7272,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
72087272 ir_build_return(irb, coro_scope, node, undef);
72097273
72107274 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
7211 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
7275 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
72127276 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
72137277
72147278 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
......@@ -7286,8 +7350,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
72867350 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
72877351 false, false, PtrLenUnknown, 0, 0, 0));
72887352 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7289 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
7290 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,
7353 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
7354 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
72917355 irb->exec->coro_result_field_ptr);
72927356 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
72937357 fn_entry->type_entry->data.fn.fn_type_id.return_type);
......@@ -7303,7 +7367,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
73037367 // Before we destroy the coroutine frame, we need to load the target promise into
73047368 // a register or local variable which does not get spilled into the frame,
73057369 // otherwise llvm tries to access memory inside the destroyed frame.
7306 IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,
7370 IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,
73077371 irb->exec->await_handle_var_ptr, false);
73087372 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
73097373 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
......@@ -7338,7 +7402,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
73387402 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
73397403 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
73407404 false, false, PtrLenUnknown, 0, 0, 0));
7341 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
7405 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
73427406 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
73437407 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
73447408 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
......@@ -7435,7 +7499,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
74357499 return val;
74367500}
74377501
7438static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
7502static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
74397503 IrBasicBlock *bb = exec->basic_block_list.at(0);
74407504 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
74417505 IrInstruction *instruction = bb->instruction_list.at(i);
......@@ -7445,16 +7509,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
74457509 if (value->value.special == ConstValSpecialRuntime) {
74467510 exec_add_error_node(codegen, exec, value->source_node,
74477511 buf_sprintf("unable to evaluate constant expression"));
7448 return codegen->invalid_instruction;
7512 return &codegen->invalid_instruction->value;
74497513 }
7450 return value;
7514 return &value->value;
74517515 } else if (ir_has_side_effects(instruction)) {
74527516 exec_add_error_node(codegen, exec, instruction->source_node,
74537517 buf_sprintf("unable to evaluate constant expression"));
7454 return codegen->invalid_instruction;
7518 return &codegen->invalid_instruction->value;
74557519 }
74567520 }
7457 return codegen->invalid_instruction;
7521 return &codegen->invalid_instruction->value;
74587522}
74597523
74607524static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
......@@ -8768,13 +8832,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
87688832 size_t errors_count = 0;
87698833 ZigType *err_set_type = nullptr;
87708834 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
8835 if (!resolve_inferred_error_set(ira->codegen, prev_inst->value.type, prev_inst->source_node)) {
8836 return ira->codegen->builtin_types.entry_invalid;
8837 }
87718838 if (type_is_global_error_set(prev_inst->value.type)) {
87728839 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
87738840 } else {
87748841 err_set_type = prev_inst->value.type;
8775 if (!resolve_inferred_error_set(ira->codegen, err_set_type, prev_inst->source_node)) {
8776 return ira->codegen->builtin_types.entry_invalid;
8777 }
87788842 update_errors_helper(ira->codegen, &errors, &errors_count);
87798843
87808844 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
......@@ -8933,6 +8997,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
89338997 if (prev_type->id == ZigTypeIdArray) {
89348998 convert_to_const_slice = true;
89358999 }
9000 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
9001 return ira->codegen->builtin_types.entry_invalid;
9002 }
89369003 if (type_is_global_error_set(cur_type)) {
89379004 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
89389005 continue;
......@@ -8940,9 +9007,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
89409007 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {
89419008 continue;
89429009 }
8943 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
8944 return ira->codegen->builtin_types.entry_invalid;
8945 }
89469010
89479011 update_errors_helper(ira->codegen, &errors, &errors_count);
89489012
......@@ -9432,14 +9496,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
94329496 }
94339497 return true;
94349498}
9499
9500static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
9501 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9502 old_instruction->scope, old_instruction->source_node);
9503 IrInstruction *new_instruction = &const_instruction->base;
9504 new_instruction->value.type = ty;
9505 new_instruction->value.special = ConstValSpecialStatic;
9506 return new_instruction;
9507}
9508
94359509static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
94369510 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
94379511{
94389512 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
94399513 cast_op != CastOpResizeSlice)
94409514 {
9441 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9442 source_instr->source_node, wanted_type);
9515 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
94439516 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
94449517 &result->value, wanted_type))
94459518 {
......@@ -9476,9 +9549,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
94769549 if (pointee == nullptr)
94779550 return ira->codegen->invalid_instruction;
94789551 if (pointee->special != ConstValSpecialRuntime) {
9479 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9480 source_instr->source_node, wanted_type);
9481 result->value.type = wanted_type;
9552 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
94829553 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;
94839554 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
94849555 result->value.data.x_ptr.data.base_array.array_val = pointee;
......@@ -9517,8 +9588,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
95179588 assert(is_slice(wanted_type));
95189589 bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
95199590
9520 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9521 source_instr->source_node, wanted_type);
9591 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
95229592 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
95239593 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =
95249594 value->value.data.x_ptr.mut;
......@@ -9653,15 +9723,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)
96539723 return instruction;
96549724}
96559725
9656static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
9657 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9658 old_instruction->scope, old_instruction->source_node);
9659 IrInstruction *new_instruction = &const_instruction->base;
9660 new_instruction->value.type = ty;
9661 new_instruction->value.special = ConstValSpecialStatic;
9662 return new_instruction;
9663}
9664
96659726static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
96669727 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);
96679728 result->value.data.x_type = ty;
......@@ -9719,13 +9780,13 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
97199780 zig_unreachable();
97209781}
97219782
9722IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
9783ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
97239784 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
97249785 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
97259786 IrExecutable *parent_exec)
97269787{
97279788 if (expected_type != nullptr && type_is_invalid(expected_type))
9728 return codegen->invalid_instruction;
9789 return &codegen->invalid_instruction->value;
97299790
97309791 IrExecutable *ir_executable = allocate<IrExecutable>(1);
97319792 ir_executable->source_node = source_node;
......@@ -9738,13 +9799,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
97389799 ir_gen(codegen, node, scope, ir_executable);
97399800
97409801 if (ir_executable->invalid)
9741 return codegen->invalid_instruction;
9802 return &codegen->invalid_instruction->value;
97429803
97439804 if (codegen->verbose_ir) {
97449805 fprintf(stderr, "\nSource: ");
97459806 ast_render(codegen, stderr, node, 4);
97469807 fprintf(stderr, "\n{ // (IR)\n");
9747 ir_print(codegen, stderr, ir_executable, 4);
9808 ir_print(codegen, stderr, ir_executable, 2);
97489809 fprintf(stderr, "}\n");
97499810 }
97509811 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
......@@ -9760,11 +9821,11 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
97609821 analyzed_executable->begin_scope = scope;
97619822 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);
97629823 if (type_is_invalid(result_type))
9763 return codegen->invalid_instruction;
9824 return &codegen->invalid_instruction->value;
97649825
97659826 if (codegen->verbose_ir) {
97669827 fprintf(stderr, "{ // (analyzed)\n");
9767 ir_print(codegen, stderr, analyzed_executable, 4);
9828 ir_print(codegen, stderr, analyzed_executable, 2);
97689829 fprintf(stderr, "}\n");
97699830 }
97709831
......@@ -9838,7 +9899,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
98389899 return const_val->data.x_ptr.data.fn.fn_entry;
98399900}
98409901
9841static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {
9902static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
9903 ZigType *wanted_type)
9904{
98429905 assert(wanted_type->id == ZigTypeIdOptional);
98439906
98449907 if (instr_is_comptime(value)) {
......@@ -9854,7 +9917,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
98549917 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
98559918 source_instr->scope, source_instr->source_node);
98569919 const_instruction->base.value.special = ConstValSpecialStatic;
9857 if (get_codegen_ptr_type(wanted_type) != nullptr) {
9920 if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) {
98589921 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
98599922 } else {
98609923 const_instruction->base.value.data.x_optional = val;
......@@ -9885,11 +9948,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
98859948 if (!val)
98869949 return ira->codegen->invalid_instruction;
98879950
9951 ConstExprValue *err_set_val = create_const_vals(1);
9952 err_set_val->type = wanted_type->data.error_union.err_set_type;
9953 err_set_val->special = ConstValSpecialStatic;
9954 err_set_val->data.x_err_set = nullptr;
9955
98889956 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
98899957 source_instr->scope, source_instr->source_node);
98909958 const_instruction->base.value.type = wanted_type;
98919959 const_instruction->base.value.special = ConstValSpecialStatic;
9892 const_instruction->base.value.data.x_err_union.err = nullptr;
9960 const_instruction->base.value.data.x_err_union.error_set = err_set_val;
98939961 const_instruction->base.value.data.x_err_union.payload = val;
98949962 return &const_instruction->base;
98959963 }
......@@ -9954,11 +10022,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
995410022 if (!val)
995510023 return ira->codegen->invalid_instruction;
995610024
10025 ConstExprValue *err_set_val = create_const_vals(1);
10026 err_set_val->special = ConstValSpecialStatic;
10027 err_set_val->type = wanted_type->data.error_union.err_set_type;
10028 err_set_val->data.x_err_set = val->data.x_err_set;
10029
995710030 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
995810031 source_instr->scope, source_instr->source_node);
995910032 const_instruction->base.value.type = wanted_type;
996010033 const_instruction->base.value.special = ConstValSpecialStatic;
9961 const_instruction->base.value.data.x_err_union.err = val->data.x_err_set;
10034 const_instruction->base.value.data.x_err_union.error_set = err_set_val;
996210035 const_instruction->base.value.data.x_err_union.payload = nullptr;
996310036 return &const_instruction->base;
996410037 }
......@@ -9980,8 +10053,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
998010053 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);
998110054 const_instruction->base.value.special = ConstValSpecialStatic;
998210055 if (get_codegen_ptr_type(wanted_type) != nullptr) {
9983 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
9984 const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0;
10056 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;
10057 } else if (is_opt_err_set(wanted_type)) {
10058 const_instruction->base.value.data.x_err_set = nullptr;
998510059 } else {
998610060 const_instruction->base.value.data.x_optional = nullptr;
998710061 }
......@@ -10014,7 +10088,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
1001410088 source_instruction->source_node, value, is_const, is_volatile);
1001510089 new_instruction->value.type = ptr_type;
1001610090 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
10017 if (type_has_bits(ptr_type)) {
10091 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
1001810092 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
1001910093 assert(fn_entry);
1002010094 fn_entry->alloca_list.append(new_instruction);
......@@ -10040,20 +10114,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
1004010114 ZigType *array_type = array->value.type;
1004110115 assert(array_type->id == ZigTypeIdArray);
1004210116
10043 if (instr_is_comptime(array)) {
10044 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10045 source_instr->source_node, wanted_type);
10117 if (instr_is_comptime(array) || array_type->data.array.len == 0) {
10118 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1004610119 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);
1004710120 result->value.type = wanted_type;
1004810121 return result;
1004910122 }
1005010123
10051 IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope,
10052 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10124 IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
1005310125 init_const_usize(ira->codegen, &start->value, 0);
1005410126
10055 IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope,
10056 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10127 IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
1005710128 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);
1005810129
1005910130 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
......@@ -10092,8 +10163,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
1009210163 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
1009310164 if (!val)
1009410165 return ira->codegen->invalid_instruction;
10095 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10096 source_instr->source_node, wanted_type);
10166 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1009710167 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
1009810168 return result;
1009910169 }
......@@ -10103,8 +10173,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
1010310173 actual_type->data.enumeration.src_field_count == 1)
1010410174 {
1010510175 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
10106 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10107 source_instr->source_node, wanted_type);
10176 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1010810177 init_const_bigint(&result->value, wanted_type,
1010910178 &actual_type->data.enumeration.fields[0].value);
1011010179 return result;
......@@ -10127,8 +10196,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
1012710196 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
1012810197 if (!val)
1012910198 return ira->codegen->invalid_instruction;
10130 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10131 source_instr->source_node, wanted_type);
10199 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1013210200 result->value.special = ConstValSpecialStatic;
1013310201 result->value.type = wanted_type;
1013410202 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);
......@@ -10139,8 +10207,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
1013910207 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
1014010208 wanted_type->data.enumeration.src_field_count == 1)
1014110209 {
10142 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10143 source_instr->source_node, wanted_type);
10210 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1014410211 result->value.special = ConstValSpecialStatic;
1014510212 result->value.type = wanted_type;
1014610213 TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;
......@@ -10157,8 +10224,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
1015710224static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
1015810225 IrInstruction *target, ZigType *wanted_type)
1015910226{
10160 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10161 source_instr->source_node, wanted_type);
10227 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1016210228 init_const_undefined(ira->codegen, &result->value);
1016310229 return result;
1016410230}
......@@ -10190,8 +10256,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
1019010256 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
1019110257 return ira->codegen->invalid_instruction;
1019210258 }
10193 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10194 source_instr->source_node, wanted_type);
10259 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1019510260 result->value.special = ConstValSpecialStatic;
1019610261 result->value.type = wanted_type;
1019710262 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);
......@@ -10246,8 +10311,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
1024610311 return ira->codegen->invalid_instruction;
1024710312 }
1024810313 }
10249 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10250 source_instr->source_node, wanted_type);
10314 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1025110315 result->value.type = wanted_type;
1025210316 if (wanted_type->id == ZigTypeIdInt) {
1025310317 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);
......@@ -10301,8 +10365,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
1030110365 return ira->codegen->invalid_instruction;
1030210366 }
1030310367
10304 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10305 source_instr->source_node, wanted_type);
10368 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1030610369 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);
1030710370 return result;
1030810371 }
......@@ -10320,8 +10383,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
1032010383 if (!val)
1032110384 return ira->codegen->invalid_instruction;
1032210385
10323 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10324 source_instr->source_node, wanted_type);
10386 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1032510387 if (wanted_type->id == ZigTypeIdComptimeFloat) {
1032610388 float_init_float(&result->value, val);
1032710389 } else if (wanted_type->id == ZigTypeIdComptimeInt) {
......@@ -10344,8 +10406,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
1034410406 if (!val)
1034510407 return ira->codegen->invalid_instruction;
1034610408
10347 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10348 source_instr->source_node, wanted_type);
10409 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1034910410
1035010411 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {
1035110412 return ira->codegen->invalid_instruction;
......@@ -10409,12 +10470,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
1040910470 if (!val)
1041010471 return ira->codegen->invalid_instruction;
1041110472
10412 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10413 source_instr->source_node, wanted_type);
10473 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1041410474
1041510475 ErrorTableEntry *err;
1041610476 if (err_type->id == ZigTypeIdErrorUnion) {
10417 err = val->data.x_err_union.err;
10477 err = val->data.x_err_union.error_set->data.x_err_set;
1041810478 } else if (err_type->id == ZigTypeIdErrorSet) {
1041910479 err = val->data.x_err_set;
1042010480 } else {
......@@ -10449,15 +10509,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
1044910509 return ira->codegen->invalid_instruction;
1045010510 }
1045110511 if (err_set_type->data.error_set.err_count == 0) {
10452 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10453 source_instr->source_node, wanted_type);
10454 result->value.type = wanted_type;
10512 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1045510513 bigint_init_unsigned(&result->value.data.x_bigint, 0);
1045610514 return result;
1045710515 } else if (err_set_type->data.error_set.err_count == 1) {
10458 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10459 source_instr->source_node, wanted_type);
10460 result->value.type = wanted_type;
10516 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1046110517 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];
1046210518 bigint_init_unsigned(&result->value.data.x_bigint, err->value);
1046310519 return result;
......@@ -10504,8 +10560,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
1050410560 array_val->type = array_type;
1050510561 array_val->data.x_array.special = ConstArraySpecialNone;
1050610562 array_val->data.x_array.data.s_none.elements = pointee;
10507 array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar;
10508 array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee;
10563 array_val->parent.id = ConstParentIdScalar;
10564 array_val->parent.data.p_scalar.scalar_val = pointee;
1050910565
1051010566 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
1051110567 source_instr->scope, source_instr->source_node);
......@@ -10653,12 +10709,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1065310709 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
1065410710 false).id == ConstCastResultIdOk)
1065510711 {
10656 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10712 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
1065710713 } else if (actual_type->id == ZigTypeIdComptimeInt ||
1065810714 actual_type->id == ZigTypeIdComptimeFloat)
1065910715 {
1066010716 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
10661 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10717 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
1066210718 } else {
1066310719 return ira->codegen->invalid_instruction;
1066410720 }
......@@ -10682,7 +10738,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1068210738 wanted_child_type);
1068310739 if (type_is_invalid(cast1->value.type))
1068410740 return ira->codegen->invalid_instruction;
10685 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
10741 return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type);
1068610742 }
1068710743 }
1068810744 }
......@@ -10735,6 +10791,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1073510791 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
1073610792 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
1073710793 {
10794 if (value->value.special == ConstValSpecialUndef) {
10795 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10796 result->value.special = ConstValSpecialUndef;
10797 return result;
10798 }
1073810799 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
1073910800 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
1074010801 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
......@@ -10788,6 +10849,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1078810849
1078910850
1079010851 // cast from [N]T to []const T
10852 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
1079110853 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
1079210854 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
1079310855 assert(ptr_type->id == ZigTypeIdPointer);
......@@ -10800,6 +10862,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1080010862 }
1080110863
1080210864 // cast from [N]T to ?[]const T
10865 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
1080310866 if (wanted_type->id == ZigTypeIdOptional &&
1080410867 is_slice(wanted_type->data.maybe.child_type) &&
1080510868 actual_type->id == ZigTypeIdArray)
......@@ -10894,7 +10957,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1089410957 }
1089510958 }
1089610959
10897 // cast from error set to error union type
10960 // cast from E to E!T
1089810961 if (wanted_type->id == ZigTypeIdErrorUnion &&
1089910962 actual_type->id == ZigTypeIdErrorSet)
1090010963 {
......@@ -11046,8 +11109,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1104611109 ZigType *child_type = type_entry->data.pointer.child_type;
1104711110 // dereferencing a *u0 is comptime known to be 0
1104811111 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
11049 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
11050 source_instruction->source_node, child_type);
11112 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1105111113 init_const_unsigned_negative(&result->value, child_type, 0, false);
1105211114 return result;
1105311115 }
......@@ -11061,8 +11123,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1106111123 {
1106211124 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
1106311125 if (pointee->special != ConstValSpecialRuntime) {
11064 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
11065 source_instruction->source_node, child_type);
11126 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1106611127
1106711128 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
1106811129 &ptr->value)))
......@@ -11074,7 +11135,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1107411135 }
1107511136 }
1107611137 }
11077 // TODO if the instruction is a const ref instruction we can skip it
11138 // if the instruction is a const ref instruction we can skip it
11139 if (ptr->id == IrInstructionIdRef) {
11140 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
11141 return ref_inst->value;
11142 }
1107811143 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
1107911144 source_instruction->source_node, ptr);
1108011145 load_ptr_instruction->value.type = child_type;
......@@ -11321,8 +11386,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
1132111386
1132211387static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
1132311388 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
11324 // TODO determine if we need to use copy_const_val here
11325 result->value = instruction->base.value;
11389 copy_const_val(&result->value, &instruction->base.value, true);
1132611390 return result;
1132711391}
1132811392
......@@ -11397,6 +11461,8 @@ static bool optional_value_is_null(ConstExprValue *val) {
1139711461 if (get_codegen_ptr_type(val->type) != nullptr) {
1139811462 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
1139911463 val->data.x_ptr.data.hard_coded_addr.addr == 0;
11464 } else if (is_opt_err_set(val->type)) {
11465 return val->data.x_err_set == nullptr;
1140011466 } else {
1140111467 return val->data.x_optional == nullptr;
1140211468 }
......@@ -11596,19 +11662,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1159611662 if (casted_op2 == ira->codegen->invalid_instruction)
1159711663 return ira->codegen->invalid_instruction;
1159811664
11599 bool requires_comptime;
11600 switch (type_requires_comptime(ira->codegen, resolved_type)) {
11601 case ReqCompTimeYes:
11602 requires_comptime = true;
11665 bool one_possible_value;
11666 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
11667 case OnePossibleValueInvalid:
11668 return ira->codegen->invalid_instruction;
11669 case OnePossibleValueYes:
11670 one_possible_value = true;
1160311671 break;
11604 case ReqCompTimeNo:
11605 requires_comptime = false;
11672 case OnePossibleValueNo:
11673 one_possible_value = false;
1160611674 break;
11607 case ReqCompTimeInvalid:
11608 return ira->codegen->invalid_instruction;
1160911675 }
1161011676
11611 bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type);
1161211677 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
1161311678 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
1161411679 if (op1_val == nullptr)
......@@ -12497,13 +12562,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio
1249712562 zig_unreachable();
1249812563}
1249912564
12500static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {
12565static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
12566 IrInstructionDeclVarSrc *decl_var_instruction)
12567{
1250112568 Error err;
1250212569 ZigVar *var = decl_var_instruction->var;
1250312570
1250412571 IrInstruction *init_value = decl_var_instruction->init_value->child;
1250512572 if (type_is_invalid(init_value->value.type)) {
12506 var->value->type = ira->codegen->builtin_types.entry_invalid;
12573 var->var_type = ira->codegen->builtin_types.entry_invalid;
1250712574 return ira->codegen->invalid_instruction;
1250812575 }
1250912576
......@@ -12514,7 +12581,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1251412581 ZigType *proposed_type = ir_resolve_type(ira, var_type);
1251512582 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
1251612583 if (type_is_invalid(explicit_type)) {
12517 var->value->type = ira->codegen->builtin_types.entry_invalid;
12584 var->var_type = ira->codegen->builtin_types.entry_invalid;
1251812585 return ira->codegen->invalid_instruction;
1251912586 }
1252012587 }
......@@ -12539,7 +12606,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1253912606 case ReqCompTimeInvalid:
1254012607 result_type = ira->codegen->builtin_types.entry_invalid;
1254112608 break;
12542 case ReqCompTimeYes: {
12609 case ReqCompTimeYes:
1254312610 var_class_requires_const = true;
1254412611 if (!var->gen_is_const && !is_comptime_var) {
1254512612 ir_add_error_node(ira, source_node,
......@@ -12548,7 +12615,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1254812615 result_type = ira->codegen->builtin_types.entry_invalid;
1254912616 }
1255012617 break;
12551 }
1255212618 case ReqCompTimeNo:
1255312619 if (casted_init_value->value.special == ConstValSpecialStatic &&
1255412620 casted_init_value->value.type->id == ZigTypeIdFn &&
......@@ -12567,7 +12633,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1256712633 break;
1256812634 }
1256912635
12570 if (var->value->type != nullptr && !is_comptime_var) {
12636 if (var->var_type != nullptr && !is_comptime_var) {
1257112637 // This is at least the second time we've seen this variable declaration during analysis.
1257212638 // This means that this is actually a different variable due to, e.g. an inline while loop.
1257312639 // We make a new variable so that it can hold a different type, and so the debug info can
......@@ -12589,8 +12655,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1258912655 // This must be done after possibly creating a new variable above
1259012656 var->ref_count = 0;
1259112657
12592 var->value->type = result_type;
12593 assert(var->value->type);
12658 var->var_type = result_type;
12659 assert(var->var_type);
1259412660
1259512661 if (type_is_invalid(result_type)) {
1259612662 return ir_const_void(ira, &decl_var_instruction->base);
......@@ -12598,13 +12664,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1259812664
1259912665 if (decl_var_instruction->align_value == nullptr) {
1260012666 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
12601 var->value->type = ira->codegen->builtin_types.entry_invalid;
12667 var->var_type = ira->codegen->builtin_types.entry_invalid;
1260212668 return ir_const_void(ira, &decl_var_instruction->base);
1260312669 }
1260412670 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
1260512671 } else {
1260612672 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {
12607 var->value->type = ira->codegen->builtin_types.entry_invalid;
12673 var->var_type = ira->codegen->builtin_types.entry_invalid;
1260812674 }
1260912675 }
1261012676
......@@ -12621,7 +12687,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1262112687 } else if (is_comptime_var) {
1262212688 ir_add_error(ira, &decl_var_instruction->base,
1262312689 buf_sprintf("cannot store runtime value in compile time variable"));
12624 var->value->type = ira->codegen->builtin_types.entry_invalid;
12690 var->var_type = ira->codegen->builtin_types.entry_invalid;
1262512691 return ira->codegen->invalid_instruction;
1262612692 }
1262712693
......@@ -12629,11 +12695,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1262912695 if (fn_entry)
1263012696 fn_entry->variable_list.append(var);
1263112697
12632 IrInstruction *result = ir_build_var_decl(&ira->new_irb,
12633 decl_var_instruction->base.scope, decl_var_instruction->base.source_node,
12634 var, var_type, nullptr, casted_init_value);
12635 result->value.type = ira->codegen->builtin_types.entry_void;
12636 return result;
12698 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
1263712699}
1263812700
1263912701static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
......@@ -12963,7 +13025,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
1296313025
1296413026 Buf *param_name = param_decl_node->data.param_decl.name;
1296513027 ZigVar *var = add_variable(ira->codegen, param_decl_node,
12966 *exec_scope, param_name, true, arg_val, nullptr);
13028 *exec_scope, param_name, true, arg_val, nullptr, arg_val->type);
1296713029 *exec_scope = var->child_scope;
1296813030 *next_proto_i += 1;
1296913031
......@@ -13021,7 +13083,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
1302113083 if (!param_name) return false;
1302213084 if (!is_var_args) {
1302313085 ZigVar *var = add_variable(ira->codegen, param_decl_node,
13024 *child_scope, param_name, true, arg_val, nullptr);
13086 *child_scope, param_name, true, arg_val, nullptr, arg_val->type);
1302513087 *child_scope = var->child_scope;
1302613088 var->shadowable = !comptime_arg;
1302713089
......@@ -13075,9 +13137,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
1307513137 return fn_entry->variable_list.at(next_var_i);
1307613138}
1307713139
13078static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13079 ZigVar *var)
13080{
13140static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) {
1308113141 while (var->next_var != nullptr) {
1308213142 var = var->next_var;
1308313143 }
......@@ -13086,14 +13146,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1308613146 assert(ira->codegen->errors.length != 0);
1308713147 return ira->codegen->invalid_instruction;
1308813148 }
13089 if (var->value->type == nullptr || type_is_invalid(var->value->type))
13149 if (var->var_type == nullptr || type_is_invalid(var->var_type))
1309013150 return ira->codegen->invalid_instruction;
1309113151
1309213152 bool comptime_var_mem = ir_get_var_is_comptime(var);
1309313153
1309413154 ConstExprValue *mem_slot = nullptr;
13095 if (var->value->special == ConstValSpecialStatic) {
13096 mem_slot = var->value;
13155 if (var->const_value->special == ConstValSpecialStatic) {
13156 mem_slot = var->const_value;
1309713157 } else {
1309813158 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
1309913159 // find the relevant exec_context
......@@ -13122,7 +13182,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1312213182 assert(!comptime_var_mem);
1312313183 ptr_mut = ConstPtrMutRuntimeVar;
1312413184 }
13125 return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type,
13185 return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type,
1312613186 ptr_mut, is_const, is_volatile, var->align_bytes);
1312713187 }
1312813188 }
......@@ -13133,7 +13193,7 @@ no_mem_slot:
1313313193
1313413194 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
1313513195 instruction->scope, instruction->source_node, var);
13136 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,
13196 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,
1313713197 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
1313813198
1313913199 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
......@@ -13142,6 +13202,96 @@ no_mem_slot:
1314213202 return var_ptr_instruction;
1314313203}
1314413204
13205static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
13206 IrInstruction *ptr, IrInstruction *uncasted_value)
13207{
13208 if (ptr->value.type->id != ZigTypeIdPointer) {
13209 ir_add_error(ira, ptr,
13210 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
13211 return ira->codegen->invalid_instruction;
13212 }
13213
13214 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
13215 return ir_const_void(ira, source_instr);
13216 }
13217
13218 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
13219 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13220 return ira->codegen->invalid_instruction;
13221 }
13222
13223 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13224 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
13225 if (value == ira->codegen->invalid_instruction)
13226 return ira->codegen->invalid_instruction;
13227
13228 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
13229 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
13230 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13231 return ira->codegen->invalid_instruction;
13232 }
13233 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
13234 if (instr_is_comptime(value)) {
13235 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
13236 if (dest_val == nullptr)
13237 return ira->codegen->invalid_instruction;
13238 if (dest_val->special != ConstValSpecialRuntime) {
13239 // TODO this allows a value stored to have the original value modified and then
13240 // have that affect what should be a copy. We need some kind of advanced copy-on-write
13241 // system to make these two tests pass at the same time:
13242 // * "string literal used as comptime slice is memoized"
13243 // * "comptime modification of const struct field" - except modified to avoid
13244 // ConstPtrMutComptimeVar, thus defeating the logic below.
13245 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
13246 copy_const_val(dest_val, &value->value, same_global_refs);
13247 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
13248 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13249 case OnePossibleValueInvalid:
13250 return ira->codegen->invalid_instruction;
13251 case OnePossibleValueNo:
13252 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
13253 break;
13254 case OnePossibleValueYes:
13255 break;
13256 }
13257 }
13258 return ir_const_void(ira, source_instr);
13259 }
13260 }
13261 ir_add_error(ira, source_instr,
13262 buf_sprintf("cannot store runtime value in compile time variable"));
13263 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
13264 dest_val->type = ira->codegen->builtin_types.entry_invalid;
13265
13266 return ira->codegen->invalid_instruction;
13267 }
13268 }
13269
13270 switch (type_requires_comptime(ira->codegen, child_type)) {
13271 case ReqCompTimeInvalid:
13272 return ira->codegen->invalid_instruction;
13273 case ReqCompTimeYes:
13274 switch (type_has_one_possible_value(ira->codegen, ptr->value.type)) {
13275 case OnePossibleValueInvalid:
13276 return ira->codegen->invalid_instruction;
13277 case OnePossibleValueNo:
13278 ir_add_error(ira, source_instr,
13279 buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name)));
13280 return ira->codegen->invalid_instruction;
13281 case OnePossibleValueYes:
13282 return ir_const_void(ira, source_instr);
13283 }
13284 zig_unreachable();
13285 case ReqCompTimeNo:
13286 break;
13287 }
13288
13289 IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
13290 ptr, value);
13291 result->value.type = ira->codegen->builtin_types.entry_void;
13292 return result;
13293}
13294
1314513295static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
1314613296 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
1314713297 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
......@@ -13286,7 +13436,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1328613436 }
1328713437
1328813438 bool cacheable = fn_eval_cacheable(exec_scope, return_type);
13289 IrInstruction *result = nullptr;
13439 ConstExprValue *result = nullptr;
1329013440 if (cacheable) {
1329113441 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
1329213442 if (entry)
......@@ -13302,18 +13452,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1330213452
1330313453 if (inferred_err_set_type != nullptr) {
1330413454 inferred_err_set_type->data.error_set.infer_fn = nullptr;
13305 if (result->value.type->id == ZigTypeIdErrorUnion) {
13306 if (result->value.data.x_err_union.err != nullptr) {
13455 if (result->type->id == ZigTypeIdErrorUnion) {
13456 ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
13457 if (err != nullptr) {
1330713458 inferred_err_set_type->data.error_set.err_count = 1;
1330813459 inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1);
13309 inferred_err_set_type->data.error_set.errors[0] = result->value.data.x_err_union.err;
13460 inferred_err_set_type->data.error_set.errors[0] = err;
1331013461 }
13311 ZigType *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type;
13462 ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type;
1331213463 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
1331313464 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;
13314 } else if (result->value.type->id == ZigTypeIdErrorSet) {
13315 inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count;
13316 inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors;
13465 } else if (result->type->id == ZigTypeIdErrorSet) {
13466 inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count;
13467 inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors;
1331713468 }
1331813469 }
1331913470
......@@ -13321,13 +13472,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1332113472 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
1332213473 }
1332313474
13324 if (type_is_invalid(result->value.type))
13475 if (type_is_invalid(result->type))
1332513476 return ira->codegen->invalid_instruction;
1332613477 }
1332713478
13328 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type);
13329 // TODO should we use copy_const_val?
13330 new_instruction->value = result->value;
13479 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);
13480 copy_const_val(&new_instruction->value, result, true);
1333113481 new_instruction->value.type = return_type;
1333213482 return ir_finish_anal(ira, new_instruction);
1333313483 }
......@@ -13486,18 +13636,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1348613636 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,
1348713637 first_var_arg, inst_fn_type_id.param_count);
1348813638 ZigVar *var = add_variable(ira->codegen, param_decl_node,
13489 impl_fn->child_scope, param_name, true, var_args_val, nullptr);
13639 impl_fn->child_scope, param_name, true, var_args_val, nullptr, var_args_val->type);
1349013640 impl_fn->child_scope = var->child_scope;
1349113641 }
1349213642
1349313643 if (fn_proto_node->data.fn_proto.align_expr != nullptr) {
13494 IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
13644 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
1349513645 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
1349613646 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
1349713647 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);
13648 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
13649 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
13650 const_instruction->base.value = *align_result;
1349813651
1349913652 uint32_t align_bytes = 0;
13500 ir_resolve_align(ira, align_result, &align_bytes);
13653 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
1350113654 impl_fn->align_bytes = align_bytes;
1350213655 inst_fn_type_id.alignment = align_bytes;
1350313656 }
......@@ -13575,12 +13728,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1357513728 ira->codegen->fn_defs.append(impl_fn);
1357613729 }
1357713730
13578 ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
13579 if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {
13731 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
13732 if (fn_type_can_fail(impl_fn_type_id)) {
1358013733 parent_fn_entry->calls_or_awaits_errorable_fn = true;
1358113734 }
1358213735
13583 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;
13736 size_t impl_param_count = impl_fn_type_id->param_count;
1358413737 if (call_instruction->is_async) {
1358513738 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
1358613739 fn_ref, casted_args, impl_param_count, async_allocator_inst);
......@@ -13593,9 +13746,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1359313746 call_instruction->base.scope, call_instruction->base.source_node,
1359413747 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
1359513748 call_instruction->is_async, nullptr, casted_new_stack);
13596 new_call_instruction->value.type = return_type;
13749 new_call_instruction->value.type = impl_fn_type_id->return_type;
1359713750
13598 ir_add_alloca(ira, new_call_instruction, return_type);
13751 ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type);
1359913752
1360013753 return ir_finish_anal(ira, new_call_instruction);
1360113754 }
......@@ -13790,6 +13943,13 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1379013943 switch (ptr_val->data.x_ptr.special) {
1379113944 case ConstPtrSpecialInvalid:
1379213945 zig_unreachable();
13946 case ConstPtrSpecialNull:
13947 if (dst_size == 0)
13948 return ErrorNone;
13949 opt_ir_add_error_node(ira, codegen, source_node,
13950 buf_sprintf("attempt to read %zu bytes from null pointer",
13951 dst_size));
13952 return ErrorSemanticAnalyzeFail;
1379313953 case ConstPtrSpecialRef: {
1379413954 opt_ir_add_error_node(ira, codegen, source_node,
1379513955 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
......@@ -13822,6 +13982,9 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1382213982 return ErrorNone;
1382313983 }
1382413984 case ConstPtrSpecialBaseStruct:
13985 case ConstPtrSpecialBaseErrorUnionCode:
13986 case ConstPtrSpecialBaseErrorUnionPayload:
13987 case ConstPtrSpecialBaseOptionalPayload:
1382513988 case ConstPtrSpecialDiscard:
1382613989 case ConstPtrSpecialHardCodedAddr:
1382713990 case ConstPtrSpecialFunction:
......@@ -14017,9 +14180,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
1401714180 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
1401814181 return ir_unreach_error(ira);
1401914182
14020 if (is_comptime || instr_is_comptime(condition)) {
14183 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
14184 IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
14185 if (type_is_invalid(casted_condition->value.type))
14186 return ir_unreach_error(ira);
14187
14188 if (is_comptime || instr_is_comptime(casted_condition)) {
1402114189 bool cond_is_true;
14022 if (!ir_resolve_bool(ira, condition, &cond_is_true))
14190 if (!ir_resolve_bool(ira, casted_condition, &cond_is_true))
1402314191 return ir_unreach_error(ira);
1402414192
1402514193 IrBasicBlock *old_dest_block = cond_is_true ?
......@@ -14038,11 +14206,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
1403814206 return ir_finish_anal(ira, result);
1403914207 }
1404014208
14041 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
14042 IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
14043 if (casted_condition == ira->codegen->invalid_instruction)
14044 return ir_unreach_error(ira);
14045
1404614209 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);
1404714210 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);
1404814211 if (new_then_block == nullptr)
......@@ -14081,8 +14244,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1408114244
1408214245 if (value->value.special != ConstValSpecialRuntime) {
1408314246 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);
14084 // TODO use copy_const_val?
14085 result->value = value->value;
14247 copy_const_val(&result->value, &value->value, true);
1408614248 return result;
1408714249 } else {
1408814250 return value;
......@@ -14131,14 +14293,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1413114293 if (type_is_invalid(resolved_type))
1413214294 return ira->codegen->invalid_instruction;
1413314295
14134 if (resolved_type->id == ZigTypeIdComptimeFloat ||
14135 resolved_type->id == ZigTypeIdComptimeInt ||
14136 resolved_type->id == ZigTypeIdNull ||
14137 resolved_type->id == ZigTypeIdUndefined)
14138 {
14296 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
14297 case OnePossibleValueInvalid:
14298 return ira->codegen->invalid_instruction;
14299 case OnePossibleValueYes:
14300 return ir_const(ira, &phi_instruction->base, resolved_type);
14301 case OnePossibleValueNo:
14302 break;
14303 }
14304
14305 switch (type_requires_comptime(ira->codegen, resolved_type)) {
14306 case ReqCompTimeInvalid:
14307 return ira->codegen->invalid_instruction;
14308 case ReqCompTimeYes:
1413914309 ir_add_error_node(ira, phi_instruction->base.source_node,
14140 buf_sprintf("unable to infer expression type"));
14310 buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name)));
1414114311 return ira->codegen->invalid_instruction;
14312 case ReqCompTimeNo:
14313 break;
1414214314 }
1414314315
1414414316 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
......@@ -14428,10 +14600,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1442814600 }
1442914601 case ConstPtrSpecialBaseStruct:
1443014602 zig_panic("TODO elem ptr on a const inner struct");
14603 case ConstPtrSpecialBaseErrorUnionCode:
14604 zig_panic("TODO elem ptr on a const inner error union code");
14605 case ConstPtrSpecialBaseErrorUnionPayload:
14606 zig_panic("TODO elem ptr on a const inner error union payload");
14607 case ConstPtrSpecialBaseOptionalPayload:
14608 zig_panic("TODO elem ptr on a const inner optional payload");
1443114609 case ConstPtrSpecialHardCodedAddr:
1443214610 zig_unreachable();
1443314611 case ConstPtrSpecialFunction:
1443414612 zig_panic("TODO element ptr of a function casted to a ptr");
14613 case ConstPtrSpecialNull:
14614 zig_panic("TODO elem ptr on a null pointer");
1443514615 }
1443614616 if (new_index >= mem_size) {
1443714617 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
......@@ -14481,10 +14661,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1448114661 }
1448214662 case ConstPtrSpecialBaseStruct:
1448314663 zig_panic("TODO elem ptr on a slice backed by const inner struct");
14664 case ConstPtrSpecialBaseErrorUnionCode:
14665 zig_panic("TODO elem ptr on a slice backed by const inner error union code");
14666 case ConstPtrSpecialBaseErrorUnionPayload:
14667 zig_panic("TODO elem ptr on a slice backed by const inner error union payload");
14668 case ConstPtrSpecialBaseOptionalPayload:
14669 zig_panic("TODO elem ptr on a slice backed by const optional payload");
1448414670 case ConstPtrSpecialHardCodedAddr:
1448514671 zig_unreachable();
1448614672 case ConstPtrSpecialFunction:
1448714673 zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
14674 case ConstPtrSpecialNull:
14675 zig_panic("TODO elem ptr on a slice has a null pointer");
1448814676 }
1448914677 return result;
1449014678 } else if (array_type->id == ZigTypeIdArray) {
......@@ -15171,74 +15359,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1517115359 }
1517215360}
1517315361
15174static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
15175 IrInstruction *ptr = load_ptr_instruction->ptr->child;
15176 if (type_is_invalid(ptr->value.type))
15177 return ira->codegen->invalid_instruction;
15178 return ir_get_deref(ira, &load_ptr_instruction->base, ptr);
15179}
15180
15181static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
15182 IrInstruction *ptr = store_ptr_instruction->ptr->child;
15362static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) {
15363 IrInstruction *ptr = instruction->ptr->child;
1518315364 if (type_is_invalid(ptr->value.type))
1518415365 return ira->codegen->invalid_instruction;
1518515366
15186 IrInstruction *value = store_ptr_instruction->value->child;
15367 IrInstruction *value = instruction->value->child;
1518715368 if (type_is_invalid(value->value.type))
1518815369 return ira->codegen->invalid_instruction;
1518915370
15190 if (ptr->value.type->id != ZigTypeIdPointer) {
15191 ir_add_error(ira, ptr,
15192 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
15193 return ira->codegen->invalid_instruction;
15194 }
15195
15196 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
15197 return ir_const_void(ira, &store_ptr_instruction->base);
15198 }
15199
15200 if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) {
15201 ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
15202 return ira->codegen->invalid_instruction;
15203 }
15371 return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);
15372}
1520415373
15205 ZigType *child_type = ptr->value.type->data.pointer.child_type;
15206 IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type);
15207 if (casted_value == ira->codegen->invalid_instruction)
15374static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
15375 IrInstruction *ptr = instruction->ptr->child;
15376 if (type_is_invalid(ptr->value.type))
1520815377 return ira->codegen->invalid_instruction;
15209
15210 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
15211 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
15212 ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
15213 return ira->codegen->invalid_instruction;
15214 }
15215 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
15216 if (instr_is_comptime(casted_value)) {
15217 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, store_ptr_instruction->base.source_node);
15218 if (dest_val == nullptr)
15219 return ira->codegen->invalid_instruction;
15220 if (dest_val->special != ConstValSpecialRuntime) {
15221 *dest_val = casted_value->value;
15222 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
15223 ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base;
15224 }
15225 return ir_const_void(ira, &store_ptr_instruction->base);
15226 }
15227 }
15228 ir_add_error(ira, &store_ptr_instruction->base,
15229 buf_sprintf("cannot store runtime value in compile time variable"));
15230 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
15231 dest_val->type = ira->codegen->builtin_types.entry_invalid;
15232
15233 return ira->codegen->invalid_instruction;
15234 }
15235 }
15236
15237 IrInstruction *result = ir_build_store_ptr(&ira->new_irb,
15238 store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node,
15239 ptr, casted_value);
15240 result->value.type = ira->codegen->builtin_types.entry_void;
15241 return result;
15378 return ir_get_deref(ira, &instruction->base, ptr);
1524215379}
1524315380
1524415381static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
......@@ -15709,11 +15846,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
1570915846 zig_unreachable();
1571015847}
1571115848
15712static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
15713 IrInstruction *value = instruction->value->child;
15714 if (type_is_invalid(value->value.type))
15715 return ira->codegen->invalid_instruction;
15716
15849static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
1571715850 ZigType *type_entry = value->value.type;
1571815851
1571915852 if (type_entry->id == ZigTypeIdOptional) {
......@@ -15722,60 +15855,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
1572215855 if (!maybe_val)
1572315856 return ira->codegen->invalid_instruction;
1572415857
15725 return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val));
15858 return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val));
1572615859 }
1572715860
1572815861 IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,
15729 instruction->base.scope, instruction->base.source_node, value);
15862 source_inst->scope, source_inst->source_node, value);
1573015863 result->value.type = ira->codegen->builtin_types.entry_bool;
1573115864 return result;
1573215865 } else if (type_entry->id == ZigTypeIdNull) {
15733 return ir_const_bool(ira, &instruction->base, false);
15866 return ir_const_bool(ira, source_inst, false);
1573415867 } else {
15735 return ir_const_bool(ira, &instruction->base, true);
15868 return ir_const_bool(ira, source_inst, true);
1573615869 }
1573715870}
1573815871
15739static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
15740 IrInstructionUnwrapOptional *unwrap_maybe_instruction)
15741{
15742 IrInstruction *value = unwrap_maybe_instruction->value->child;
15872static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
15873 IrInstruction *value = instruction->value->child;
1574315874 if (type_is_invalid(value->value.type))
1574415875 return ira->codegen->invalid_instruction;
1574515876
15746 ZigType *ptr_type = value->value.type;
15877 return ir_analyze_test_non_null(ira, &instruction->base, value);
15878}
15879
15880static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
15881 IrInstruction *base_ptr, bool safety_check_on)
15882{
15883 ZigType *ptr_type = base_ptr->value.type;
1574715884 assert(ptr_type->id == ZigTypeIdPointer);
1574815885
1574915886 ZigType *type_entry = ptr_type->data.pointer.child_type;
15750 if (type_is_invalid(type_entry)) {
15887 if (type_is_invalid(type_entry))
1575115888 return ira->codegen->invalid_instruction;
15752 } else if (type_entry->id != ZigTypeIdOptional) {
15753 ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,
15889
15890 if (type_entry->id != ZigTypeIdOptional) {
15891 ir_add_error_node(ira, base_ptr->source_node,
1575415892 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
1575515893 return ira->codegen->invalid_instruction;
1575615894 }
15895
1575715896 ZigType *child_type = type_entry->data.maybe.child_type;
1575815897 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
1575915898 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
1576015899
15761 if (instr_is_comptime(value)) {
15762 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
15900 if (instr_is_comptime(base_ptr)) {
15901 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
1576315902 if (!val)
1576415903 return ira->codegen->invalid_instruction;
15765 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, unwrap_maybe_instruction->base.source_node);
15904 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
1576615905 if (maybe_val == nullptr)
1576715906 return ira->codegen->invalid_instruction;
1576815907
1576915908 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
1577015909 if (optional_value_is_null(maybe_val)) {
15771 ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null"));
15910 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
1577215911 return ira->codegen->invalid_instruction;
1577315912 }
15774 IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type);
15913 IrInstruction *result = ir_const(ira, source_instr, result_type);
1577515914 ConstExprValue *out_val = &result->value;
1577615915 out_val->data.x_ptr.special = ConstPtrSpecialRef;
1577715916 out_val->data.x_ptr.mut = val->data.x_ptr.mut;
15778 if (type_is_codegen_pointer(child_type)) {
15917 if (types_have_same_zig_comptime_repr(type_entry, child_type)) {
1577915918 out_val->data.x_ptr.data.ref.pointee = maybe_val;
1578015919 } else {
1578115920 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
......@@ -15784,13 +15923,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
1578415923 }
1578515924 }
1578615925
15787 IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb,
15788 unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node,
15789 value, unwrap_maybe_instruction->safety_check_on);
15926 IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
15927 source_instr->source_node, base_ptr, safety_check_on);
1579015928 result->value.type = result_type;
1579115929 return result;
1579215930}
1579315931
15932static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
15933 IrInstructionOptionalUnwrapPtr *instruction)
15934{
15935 IrInstruction *base_ptr = instruction->base_ptr->child;
15936 if (type_is_invalid(base_ptr->value.type))
15937 return ira->codegen->invalid_instruction;
15938
15939 return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);
15940}
15941
1579415942static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
1579515943 IrInstruction *value = ctz_instruction->value->child;
1579615944 if (type_is_invalid(value->value.type)) {
......@@ -16091,9 +16239,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1609116239 return result;
1609216240 }
1609316241
16094 IrInstruction *result = ir_build_load_ptr(&ira->new_irb,
16095 switch_target_instruction->base.scope, switch_target_instruction->base.source_node,
16096 target_value_ptr);
16242 IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1609716243 result->value.type = target_type;
1609816244 return result;
1609916245 }
......@@ -16123,8 +16269,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1612316269 return result;
1612416270 }
1612516271
16126 IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
16127 switch_target_instruction->base.source_node, target_value_ptr);
16272 IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1612816273 union_value->value.type = target_type;
1612916274
1613016275 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
......@@ -16148,8 +16293,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1614816293 return result;
1614916294 }
1615016295
16151 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
16152 switch_target_instruction->base.source_node, target_value_ptr);
16296 IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1615316297 enum_value->value.type = target_type;
1615416298 return enum_value;
1615516299 }
......@@ -16306,7 +16450,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1630616450 Error err;
1630716451 assert(container_type->id == ZigTypeIdUnion);
1630816452
16309 if ((err = ensure_complete_type(ira->codegen, container_type)))
16453 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
1631016454 return ira->codegen->invalid_instruction;
1631116455
1631216456 if (instr_field_count != 1) {
......@@ -16350,12 +16494,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1635016494 ConstExprValue *out_val = &result->value;
1635116495 out_val->data.x_union.payload = field_val;
1635216496 out_val->data.x_union.tag = type_field->enum_field->value;
16353
16354 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
16355 if (parent != nullptr) {
16356 parent->id = ConstParentIdUnion;
16357 parent->data.p_union.union_val = out_val;
16358 }
16497 out_val->parent.id = ConstParentIdUnion;
16498 out_val->parent.data.p_union.union_val = out_val;
1635916499
1636016500 return result;
1636116501 }
......@@ -16382,7 +16522,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1638216522 return ira->codegen->invalid_instruction;
1638316523 }
1638416524
16385 if ((err = ensure_complete_type(ira->codegen, container_type)))
16525 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
1638616526 return ira->codegen->invalid_instruction;
1638716527
1638816528 size_t actual_field_count = container_type->data.structure.src_field_count;
......@@ -16461,9 +16601,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1646116601 if (const_val.special == ConstValSpecialStatic) {
1646216602 IrInstruction *result = ir_const(ira, instruction, nullptr);
1646316603 ConstExprValue *out_val = &result->value;
16464 // TODO copy_const_val?
16465 *out_val = const_val;
16466 result->value.type = container_type;
16604 copy_const_val(out_val, &const_val, true);
16605 out_val->type = container_type;
1646716606
1646816607 for (size_t i = 0; i < instr_field_count; i += 1) {
1646916608 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
......@@ -16495,127 +16634,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1649516634static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1649616635 IrInstructionContainerInitList *instruction)
1649716636{
16498 IrInstruction *container_type_value = instruction->container_type->child;
16499 if (type_is_invalid(container_type_value->value.type))
16637 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
16638 if (type_is_invalid(container_type))
1650016639 return ira->codegen->invalid_instruction;
1650116640
1650216641 size_t elem_count = instruction->item_count;
16503 if (container_type_value->value.type->id == ZigTypeIdMetaType) {
16504 ZigType *container_type = ir_resolve_type(ira, container_type_value);
16505 if (type_is_invalid(container_type))
16506 return ira->codegen->invalid_instruction;
1650716642
16508 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
16509 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
16510 0, nullptr);
16511 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
16512 // array is same as slice init but we make a compile error if the length is wrong
16513 ZigType *child_type;
16514 if (container_type->id == ZigTypeIdArray) {
16515 child_type = container_type->data.array.child_type;
16516 if (container_type->data.array.len != elem_count) {
16517 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
16643 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
16644 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
16645 0, nullptr);
16646 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
16647 // array is same as slice init but we make a compile error if the length is wrong
16648 ZigType *child_type;
16649 if (container_type->id == ZigTypeIdArray) {
16650 child_type = container_type->data.array.child_type;
16651 if (container_type->data.array.len != elem_count) {
16652 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
1651816653
16519 ir_add_error(ira, &instruction->base,
16520 buf_sprintf("expected %s literal, found %s literal",
16521 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
16522 return ira->codegen->invalid_instruction;
16523 }
16524 } else {
16525 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
16526 assert(pointer_type->id == ZigTypeIdPointer);
16527 child_type = pointer_type->data.pointer.child_type;
16654 ir_add_error(ira, &instruction->base,
16655 buf_sprintf("expected %s literal, found %s literal",
16656 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
16657 return ira->codegen->invalid_instruction;
1652816658 }
16659 } else {
16660 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
16661 assert(pointer_type->id == ZigTypeIdPointer);
16662 child_type = pointer_type->data.pointer.child_type;
16663 }
1652916664
16530 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
16665 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
1653116666
16532 ConstExprValue const_val = {};
16533 const_val.special = ConstValSpecialStatic;
16534 const_val.type = fixed_size_array_type;
16535 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
16667 ConstExprValue const_val = {};
16668 const_val.special = ConstValSpecialStatic;
16669 const_val.type = fixed_size_array_type;
16670 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
1653616671
16537 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
16672 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
1653816673
16539 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
16674 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
1654016675
16541 IrInstruction *first_non_const_instruction = nullptr;
16676 IrInstruction *first_non_const_instruction = nullptr;
1654216677
16543 for (size_t i = 0; i < elem_count; i += 1) {
16544 IrInstruction *arg_value = instruction->items[i]->child;
16545 if (type_is_invalid(arg_value->value.type))
16546 return ira->codegen->invalid_instruction;
16678 for (size_t i = 0; i < elem_count; i += 1) {
16679 IrInstruction *arg_value = instruction->items[i]->child;
16680 if (type_is_invalid(arg_value->value.type))
16681 return ira->codegen->invalid_instruction;
1654716682
16548 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
16549 if (casted_arg == ira->codegen->invalid_instruction)
16550 return ira->codegen->invalid_instruction;
16683 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
16684 if (casted_arg == ira->codegen->invalid_instruction)
16685 return ira->codegen->invalid_instruction;
1655116686
16552 new_items[i] = casted_arg;
16687 new_items[i] = casted_arg;
1655316688
16554 if (const_val.special == ConstValSpecialStatic) {
16555 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
16556 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
16557 if (!elem_val)
16558 return ira->codegen->invalid_instruction;
16689 if (const_val.special == ConstValSpecialStatic) {
16690 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
16691 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
16692 if (!elem_val)
16693 return ira->codegen->invalid_instruction;
1655916694
16560 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
16561 } else {
16562 first_non_const_instruction = casted_arg;
16563 const_val.special = ConstValSpecialRuntime;
16564 }
16695 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
16696 } else {
16697 first_non_const_instruction = casted_arg;
16698 const_val.special = ConstValSpecialRuntime;
1656516699 }
1656616700 }
16701 }
1656716702
16568 if (const_val.special == ConstValSpecialStatic) {
16569 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
16570 ConstExprValue *out_val = &result->value;
16571 // TODO copy_const_val?
16572 *out_val = const_val;
16573 result->value.type = fixed_size_array_type;
16574 for (size_t i = 0; i < elem_count; i += 1) {
16575 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
16576 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
16577 if (parent != nullptr) {
16578 parent->id = ConstParentIdArray;
16579 parent->data.p_array.array_val = out_val;
16580 parent->data.p_array.elem_index = i;
16581 }
16703 if (const_val.special == ConstValSpecialStatic) {
16704 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
16705 ConstExprValue *out_val = &result->value;
16706 copy_const_val(out_val, &const_val, true);
16707 result->value.type = fixed_size_array_type;
16708 for (size_t i = 0; i < elem_count; i += 1) {
16709 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
16710 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
16711 if (parent != nullptr) {
16712 parent->id = ConstParentIdArray;
16713 parent->data.p_array.array_val = out_val;
16714 parent->data.p_array.elem_index = i;
1658216715 }
16583 return result;
1658416716 }
16717 return result;
16718 }
1658516719
16586 if (is_comptime) {
16587 ir_add_error_node(ira, first_non_const_instruction->source_node,
16588 buf_sprintf("unable to evaluate constant expression"));
16589 return ira->codegen->invalid_instruction;
16590 }
16720 if (is_comptime) {
16721 ir_add_error_node(ira, first_non_const_instruction->source_node,
16722 buf_sprintf("unable to evaluate constant expression"));
16723 return ira->codegen->invalid_instruction;
16724 }
1659116725
16592 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
16593 instruction->base.scope, instruction->base.source_node,
16594 container_type_value, elem_count, new_items);
16595 new_instruction->value.type = fixed_size_array_type;
16596 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
16597 return new_instruction;
16598 } else if (container_type->id == ZigTypeIdVoid) {
16599 if (elem_count != 0) {
16600 ir_add_error_node(ira, instruction->base.source_node,
16601 buf_sprintf("void expression expects no arguments"));
16602 return ira->codegen->invalid_instruction;
16603 }
16604 return ir_const_void(ira, &instruction->base);
16605 } else {
16726 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
16727 instruction->base.scope, instruction->base.source_node,
16728 nullptr, elem_count, new_items);
16729 new_instruction->value.type = fixed_size_array_type;
16730 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
16731 return new_instruction;
16732 } else if (container_type->id == ZigTypeIdVoid) {
16733 if (elem_count != 0) {
1660616734 ir_add_error_node(ira, instruction->base.source_node,
16607 buf_sprintf("type '%s' does not support array initialization",
16608 buf_ptr(&container_type->name)));
16735 buf_sprintf("void expression expects no arguments"));
1660916736 return ira->codegen->invalid_instruction;
1661016737 }
16738 return ir_const_void(ira, &instruction->base);
1661116739 } else {
16612 ir_add_error(ira, container_type_value,
16613 buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));
16740 ir_add_error_node(ira, instruction->base.source_node,
16741 buf_sprintf("type '%s' does not support array initialization",
16742 buf_ptr(&container_type->name)));
1661416743 return ira->codegen->invalid_instruction;
1661516744 }
1661616745}
1661716746
16618static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {
16747static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
16748 IrInstructionContainerInitFields *instruction)
16749{
1661916750 IrInstruction *container_type_value = instruction->container_type->child;
1662016751 ZigType *container_type = ir_resolve_type(ira, container_type_value);
1662116752 if (type_is_invalid(container_type))
......@@ -16675,7 +16806,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
1667516806 if (type_is_invalid(value->value.type))
1667616807 return ira->codegen->invalid_instruction;
1667716808
16678 IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type);
16809 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set);
1667916810 if (type_is_invalid(casted_value->value.type))
1668016811 return ira->codegen->invalid_instruction;
1668116812
......@@ -16936,10 +17067,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
1693617067
1693717068 ZigVar *var = tld->var;
1693817069
16939 if ((err = ensure_complete_type(ira->codegen, var->value->type)))
17070 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
1694017071 return ira->codegen->builtin_types.entry_invalid;
16941 assert(var->value->type->id == ZigTypeIdMetaType);
16942 return var->value->data.x_type;
17072
17073 assert(var->const_value->type->id == ZigTypeIdMetaType);
17074 return var->const_value->data.x_type;
1694317075}
1694417076
1694517077static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {
......@@ -16994,7 +17126,6 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1699417126 definition_array->special = ConstValSpecialStatic;
1699517127 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
1699617128 definition_array->data.x_array.special = ConstArraySpecialNone;
16997 definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1699817129 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);
1699917130 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);
1700017131
......@@ -17025,33 +17156,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1702517156 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
1702617157 inner_fields[2].special = ConstValSpecialStatic;
1702717158 inner_fields[2].type = type_info_definition_data_type;
17028 inner_fields[2].data.x_union.parent.id = ConstParentIdStruct;
17029 inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;
17030 inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;
17159 inner_fields[2].parent.id = ConstParentIdStruct;
17160 inner_fields[2].parent.data.p_struct.struct_val = definition_val;
17161 inner_fields[2].parent.data.p_struct.field_index = 1;
1703117162
1703217163 switch (curr_entry->value->id) {
1703317164 case TldIdVar:
1703417165 {
1703517166 ZigVar *var = ((TldVar *)curr_entry->value)->var;
17036 if ((err = ensure_complete_type(ira->codegen, var->value->type)))
17167 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
1703717168 return ErrorSemanticAnalyzeFail;
1703817169
17039 if (var->value->type->id == ZigTypeIdMetaType)
17040 {
17170 if (var->const_value->type->id == ZigTypeIdMetaType) {
1704117171 // We have a variable of type 'type', so it's actually a type definition.
1704217172 // 0: Data.Type: type
1704317173 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
17044 inner_fields[2].data.x_union.payload = var->value;
17045 }
17046 else
17047 {
17174 inner_fields[2].data.x_union.payload = var->const_value;
17175 } else {
1704817176 // We have a variable of another type, so we store the type of the variable.
1704917177 // 1: Data.Var: type
1705017178 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);
1705117179
1705217180 ConstExprValue *payload = create_const_vals(1);
1705317181 payload->type = ira->codegen->builtin_types.entry_type;
17054 payload->data.x_type = var->value->type;
17182 payload->data.x_type = var->const_value->type;
1705517183
1705617184 inner_fields[2].data.x_union.payload = payload;
1705717185 }
......@@ -17071,8 +17199,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1707117199 ConstExprValue *fn_def_val = create_const_vals(1);
1707217200 fn_def_val->special = ConstValSpecialStatic;
1707317201 fn_def_val->type = type_info_fn_def_type;
17074 fn_def_val->data.x_struct.parent.id = ConstParentIdUnion;
17075 fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2];
17202 fn_def_val->parent.id = ConstParentIdUnion;
17203 fn_def_val->parent.data.p_union.union_val = &inner_fields[2];
1707617204
1707717205 ConstExprValue *fn_def_fields = create_const_vals(9);
1707817206 fn_def_val->data.x_struct.fields = fn_def_fields;
......@@ -17136,20 +17264,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1713617264 fn_arg_name_array->type = get_array_type(ira->codegen,
1713717265 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
1713817266 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
17139 fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1714017267 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1714117268
1714217269 init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);
1714317270
17144 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++)
17145 {
17271 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
1714617272 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
1714717273 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
1714817274 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);
1714917275 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);
17150 fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray;
17151 fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array;
17152 fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;
17276 fn_arg_name_val->parent.id = ConstParentIdArray;
17277 fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
17278 fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index;
1715317279 }
1715417280
1715517281 inner_fields[2].data.x_union.payload = fn_def_val;
......@@ -17442,7 +17568,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1744217568 enum_field_array->special = ConstValSpecialStatic;
1744317569 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
1744417570 enum_field_array->data.x_array.special = ConstArraySpecialNone;
17445 enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1744617571 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
1744717572
1744817573 init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);
......@@ -17452,9 +17577,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1745217577 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
1745317578 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];
1745417579 make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);
17455 enum_field_val->data.x_struct.parent.id = ConstParentIdArray;
17456 enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array;
17457 enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index;
17580 enum_field_val->parent.id = ConstParentIdArray;
17581 enum_field_val->parent.data.p_array.array_val = enum_field_array;
17582 enum_field_val->parent.data.p_array.elem_index = enum_field_index;
1745817583 }
1745917584 // defs: []TypeInfo.Definition
1746017585 ensure_field_index(result->type, "defs", 3);
......@@ -17481,7 +17606,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1748117606 error_array->special = ConstValSpecialStatic;
1748217607 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
1748317608 error_array->data.x_array.special = ConstArraySpecialNone;
17484 error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1748517609 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
1748617610
1748717611 init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);
......@@ -17505,9 +17629,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1750517629 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);
1750617630
1750717631 error_val->data.x_struct.fields = inner_fields;
17508 error_val->data.x_struct.parent.id = ConstParentIdArray;
17509 error_val->data.x_struct.parent.data.p_array.array_val = error_array;
17510 error_val->data.x_struct.parent.data.p_array.elem_index = error_index;
17632 error_val->parent.id = ConstParentIdArray;
17633 error_val->parent.data.p_array.array_val = error_array;
17634 error_val->parent.data.p_array.elem_index = error_index;
1751117635 }
1751217636
1751317637 break;
......@@ -17576,7 +17700,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1757617700 union_field_array->special = ConstValSpecialStatic;
1757717701 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
1757817702 union_field_array->data.x_array.special = ConstArraySpecialNone;
17579 union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1758017703 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
1758117704
1758217705 init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);
......@@ -17609,9 +17732,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1760917732 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);
1761017733
1761117734 union_field_val->data.x_struct.fields = inner_fields;
17612 union_field_val->data.x_struct.parent.id = ConstParentIdArray;
17613 union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array;
17614 union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index;
17735 union_field_val->parent.id = ConstParentIdArray;
17736 union_field_val->parent.data.p_array.array_val = union_field_array;
17737 union_field_val->parent.data.p_array.elem_index = union_field_index;
1761517738 }
1761617739 // defs: []TypeInfo.Definition
1761717740 ensure_field_index(result->type, "defs", 3);
......@@ -17651,7 +17774,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1765117774 struct_field_array->special = ConstValSpecialStatic;
1765217775 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
1765317776 struct_field_array->data.x_array.special = ConstArraySpecialNone;
17654 struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1765517777 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
1765617778
1765717779 init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);
......@@ -17685,9 +17807,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1768517807 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);
1768617808
1768717809 struct_field_val->data.x_struct.fields = inner_fields;
17688 struct_field_val->data.x_struct.parent.id = ConstParentIdArray;
17689 struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array;
17690 struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index;
17810 struct_field_val->parent.id = ConstParentIdArray;
17811 struct_field_val->parent.data.p_array.array_val = struct_field_array;
17812 struct_field_val->parent.data.p_array.elem_index = struct_field_index;
1769117813 }
1769217814 // defs: []TypeInfo.Definition
1769317815 ensure_field_index(result->type, "defs", 2);
......@@ -17757,7 +17879,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1775717879 fn_arg_array->special = ConstValSpecialStatic;
1775817880 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
1775917881 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
17760 fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1776117882 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1776217883
1776317884 init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);
......@@ -17794,9 +17915,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1779417915 }
1779517916
1779617917 fn_arg_val->data.x_struct.fields = inner_fields;
17797 fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;
17798 fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array;
17799 fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;
17918 fn_arg_val->parent.id = ConstParentIdArray;
17919 fn_arg_val->parent.data.p_array.array_val = fn_arg_array;
17920 fn_arg_val->parent.data.p_array.elem_index = fn_arg_index;
1780017921 }
1780117922
1780217923 break;
......@@ -17840,8 +17961,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
1784017961
1784117962 if (payload != nullptr) {
1784217963 assert(payload->type->id == ZigTypeIdStruct);
17843 payload->data.x_struct.parent.id = ConstParentIdUnion;
17844 payload->data.x_struct.parent.data.p_union.union_val = out_val;
17964 payload->parent.id = ConstParentIdUnion;
17965 payload->parent.data.p_union.union_val = out_val;
1784517966 }
1784617967
1784717968 return result;
......@@ -17913,10 +18034,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1791318034
1791418035 // Execute the C import block like an inline function
1791518036 ZigType *void_type = ira->codegen->builtin_types.entry_void;
17916 IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
18037 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
1791718038 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
1791818039 &cimport_scope->buf, block_node, nullptr, nullptr);
17919 if (type_is_invalid(cimport_result->value.type))
18040 if (type_is_invalid(cimport_result->type))
1792018041 return ira->codegen->invalid_instruction;
1792118042
1792218043 find_libc_include_path(ira->codegen);
......@@ -18066,7 +18187,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
1806618187 return result;
1806718188}
1806818189
18069static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {
18190static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) {
1807018191 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
1807118192 if (type_is_invalid(operand_type))
1807218193 return ira->codegen->invalid_instruction;
......@@ -18138,9 +18259,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
1813818259 zig_panic("TODO compile-time execution of cmpxchg");
1813918260 }
1814018261
18141 IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
18142 nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak,
18143 operand_type, success_order, failure_order);
18262 IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
18263 casted_ptr, casted_cmp_value, casted_new_value,
18264 success_order, failure_order, instruction->is_weak);
1814418265 result->value.type = get_optional_type(ira->codegen, operand_type);
1814518266 ir_add_alloca(ira, result, result->value.type);
1814618267 return result;
......@@ -18312,18 +18433,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst
1831218433 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
1831318434}
1831418435
18315static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18316 Error err;
18317
18318 if (ty->id == ZigTypeIdPointer) {
18319 if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown)))
18320 return err;
18321 }
18322
18323 *result_align = get_ptr_align(ira->codegen, ty);
18324 return ErrorNone;
18325}
18326
1832718436static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
1832818437 Error err;
1832918438
......@@ -18442,6 +18551,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
1844218551 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
1844318552}
1844418553
18554static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18555 Error err;
18556
18557 ZigType *ptr_type = get_src_ptr_type(ty);
18558 assert(ptr_type != nullptr);
18559 if (ptr_type->id == ZigTypeIdPointer) {
18560 if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
18561 return err;
18562 }
18563
18564 *result_align = get_ptr_align(ira->codegen, ty);
18565 return ErrorNone;
18566}
18567
1844518568static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
1844618569 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
1844718570 if (type_is_invalid(dest_type))
......@@ -18646,10 +18769,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
1864618769 }
1864718770 case ConstPtrSpecialBaseStruct:
1864818771 zig_panic("TODO memset on const inner struct");
18772 case ConstPtrSpecialBaseErrorUnionCode:
18773 zig_panic("TODO memset on const inner error union code");
18774 case ConstPtrSpecialBaseErrorUnionPayload:
18775 zig_panic("TODO memset on const inner error union payload");
18776 case ConstPtrSpecialBaseOptionalPayload:
18777 zig_panic("TODO memset on const inner optional payload");
1864918778 case ConstPtrSpecialHardCodedAddr:
1865018779 zig_unreachable();
1865118780 case ConstPtrSpecialFunction:
1865218781 zig_panic("TODO memset on ptr cast from function");
18782 case ConstPtrSpecialNull:
18783 zig_panic("TODO memset on null ptr");
1865318784 }
1865418785
1865518786 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);
......@@ -18761,10 +18892,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
1876118892 }
1876218893 case ConstPtrSpecialBaseStruct:
1876318894 zig_panic("TODO memcpy on const inner struct");
18895 case ConstPtrSpecialBaseErrorUnionCode:
18896 zig_panic("TODO memcpy on const inner error union code");
18897 case ConstPtrSpecialBaseErrorUnionPayload:
18898 zig_panic("TODO memcpy on const inner error union payload");
18899 case ConstPtrSpecialBaseOptionalPayload:
18900 zig_panic("TODO memcpy on const inner optional payload");
1876418901 case ConstPtrSpecialHardCodedAddr:
1876518902 zig_unreachable();
1876618903 case ConstPtrSpecialFunction:
1876718904 zig_panic("TODO memcpy on ptr cast from function");
18905 case ConstPtrSpecialNull:
18906 zig_panic("TODO memcpy on null ptr");
1876818907 }
1876918908
1877018909 if (dest_start + count > dest_end) {
......@@ -18797,10 +18936,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
1879718936 }
1879818937 case ConstPtrSpecialBaseStruct:
1879918938 zig_panic("TODO memcpy on const inner struct");
18939 case ConstPtrSpecialBaseErrorUnionCode:
18940 zig_panic("TODO memcpy on const inner error union code");
18941 case ConstPtrSpecialBaseErrorUnionPayload:
18942 zig_panic("TODO memcpy on const inner error union payload");
18943 case ConstPtrSpecialBaseOptionalPayload:
18944 zig_panic("TODO memcpy on const inner optional payload");
1880018945 case ConstPtrSpecialHardCodedAddr:
1880118946 zig_unreachable();
1880218947 case ConstPtrSpecialFunction:
1880318948 zig_panic("TODO memcpy on ptr cast from function");
18949 case ConstPtrSpecialNull:
18950 zig_panic("TODO memcpy on null ptr");
1880418951 }
1880518952
1880618953 if (src_start + count > src_end) {
......@@ -18828,9 +18975,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1882818975 if (type_is_invalid(ptr_ptr->value.type))
1882918976 return ira->codegen->invalid_instruction;
1883018977
18831 ZigType *ptr_type = ptr_ptr->value.type;
18832 assert(ptr_type->id == ZigTypeIdPointer);
18833 ZigType *array_type = ptr_type->data.pointer.child_type;
18978 ZigType *ptr_ptr_type = ptr_ptr->value.type;
18979 assert(ptr_ptr_type->id == ZigTypeIdPointer);
18980 ZigType *array_type = ptr_ptr_type->data.pointer.child_type;
1883418981
1883518982 IrInstruction *start = instruction->start->child;
1883618983 if (type_is_invalid(start->value.type))
......@@ -18859,10 +19006,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1885919006 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
1886019007 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
1886119008 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
18862 ptr_type->data.pointer.is_const || is_comptime_const,
18863 ptr_type->data.pointer.is_volatile,
19009 ptr_ptr_type->data.pointer.is_const || is_comptime_const,
19010 ptr_ptr_type->data.pointer.is_volatile,
1886419011 PtrLenUnknown,
18865 ptr_type->data.pointer.explicit_alignment, 0, 0);
19012 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0);
1886619013 return_type = get_slice_type(ira->codegen, slice_ptr_type);
1886719014 } else if (array_type->id == ZigTypeIdPointer) {
1886819015 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
......@@ -18960,6 +19107,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1896019107 break;
1896119108 case ConstPtrSpecialBaseStruct:
1896219109 zig_panic("TODO slice const inner struct");
19110 case ConstPtrSpecialBaseErrorUnionCode:
19111 zig_panic("TODO slice const inner error union code");
19112 case ConstPtrSpecialBaseErrorUnionPayload:
19113 zig_panic("TODO slice const inner error union payload");
19114 case ConstPtrSpecialBaseOptionalPayload:
19115 zig_panic("TODO slice const inner optional payload");
1896319116 case ConstPtrSpecialHardCodedAddr:
1896419117 array_val = nullptr;
1896519118 abs_offset = 0;
......@@ -18967,6 +19120,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1896719120 break;
1896819121 case ConstPtrSpecialFunction:
1896919122 zig_panic("TODO slice of ptr cast from function");
19123 case ConstPtrSpecialNull:
19124 zig_panic("TODO slice of null ptr");
1897019125 }
1897119126 } else if (is_slice(array_type)) {
1897219127 ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
......@@ -18997,6 +19152,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1899719152 break;
1899819153 case ConstPtrSpecialBaseStruct:
1899919154 zig_panic("TODO slice const inner struct");
19155 case ConstPtrSpecialBaseErrorUnionCode:
19156 zig_panic("TODO slice const inner error union code");
19157 case ConstPtrSpecialBaseErrorUnionPayload:
19158 zig_panic("TODO slice const inner error union payload");
19159 case ConstPtrSpecialBaseOptionalPayload:
19160 zig_panic("TODO slice const inner optional payload");
1900019161 case ConstPtrSpecialHardCodedAddr:
1900119162 array_val = nullptr;
1900219163 abs_offset = 0;
......@@ -19004,6 +19165,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1900419165 break;
1900519166 case ConstPtrSpecialFunction:
1900619167 zig_panic("TODO slice of slice cast from function");
19168 case ConstPtrSpecialNull:
19169 zig_panic("TODO slice of null");
1900719170 }
1900819171 } else {
1900919172 zig_unreachable();
......@@ -19069,6 +19232,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1906919232 zig_unreachable();
1907019233 case ConstPtrSpecialBaseStruct:
1907119234 zig_panic("TODO");
19235 case ConstPtrSpecialBaseErrorUnionCode:
19236 zig_panic("TODO");
19237 case ConstPtrSpecialBaseErrorUnionPayload:
19238 zig_panic("TODO");
19239 case ConstPtrSpecialBaseOptionalPayload:
19240 zig_panic("TODO");
1907219241 case ConstPtrSpecialHardCodedAddr:
1907319242 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
1907419243 parent_ptr->type->data.pointer.child_type,
......@@ -19077,6 +19246,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1907719246 break;
1907819247 case ConstPtrSpecialFunction:
1907919248 zig_panic("TODO");
19249 case ConstPtrSpecialNull:
19250 zig_panic("TODO");
1908019251 }
1908119252
1908219253 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
......@@ -19432,7 +19603,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
1943219603 return ira->codegen->invalid_instruction;
1943319604
1943419605 if (err_union_val->special != ConstValSpecialRuntime) {
19435 return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr));
19606 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19607 return ir_const_bool(ira, &instruction->base, (err != nullptr));
1943619608 }
1943719609 }
1943819610
......@@ -19458,48 +19630,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
1945819630 }
1945919631}
1946019632
19461static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
19462 IrInstructionUnwrapErrCode *instruction)
19463{
19464 IrInstruction *value = instruction->value->child;
19465 if (type_is_invalid(value->value.type))
19633static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
19634 IrInstruction *base_ptr = instruction->err_union->child;
19635 if (type_is_invalid(base_ptr->value.type))
1946619636 return ira->codegen->invalid_instruction;
19467 ZigType *ptr_type = value->value.type;
19637 ZigType *ptr_type = base_ptr->value.type;
1946819638
1946919639 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
1947019640 assert(ptr_type->id == ZigTypeIdPointer);
1947119641
1947219642 ZigType *type_entry = ptr_type->data.pointer.child_type;
19473 if (type_is_invalid(type_entry)) {
19643 if (type_is_invalid(type_entry))
1947419644 return ira->codegen->invalid_instruction;
19475 } else if (type_entry->id == ZigTypeIdErrorUnion) {
19476 if (instr_is_comptime(value)) {
19477 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19478 if (!ptr_val)
19479 return ira->codegen->invalid_instruction;
19480 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19481 if (err_union_val == nullptr)
19482 return ira->codegen->invalid_instruction;
19483 if (err_union_val->special != ConstValSpecialRuntime) {
19484 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
19485 assert(err);
19486
19487 IrInstruction *result = ir_const(ira, &instruction->base,
19488 type_entry->data.error_union.err_set_type);
19489 result->value.data.x_err_set = err;
19490 return result;
19491 }
19492 }
1949319645
19494 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
19495 instruction->base.scope, instruction->base.source_node, value);
19496 result->value.type = type_entry->data.error_union.err_set_type;
19497 return result;
19498 } else {
19499 ir_add_error(ira, value,
19646 if (type_entry->id != ZigTypeIdErrorUnion) {
19647 ir_add_error(ira, base_ptr,
1950019648 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
1950119649 return ira->codegen->invalid_instruction;
1950219650 }
19651
19652 if (instr_is_comptime(base_ptr)) {
19653 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
19654 if (!ptr_val)
19655 return ira->codegen->invalid_instruction;
19656 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19657 if (err_union_val == nullptr)
19658 return ira->codegen->invalid_instruction;
19659 if (err_union_val->special != ConstValSpecialRuntime) {
19660 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19661 assert(err);
19662
19663 IrInstruction *result = ir_const(ira, &instruction->base,
19664 type_entry->data.error_union.err_set_type);
19665 result->value.data.x_err_set = err;
19666 return result;
19667 }
19668 }
19669
19670 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
19671 instruction->base.scope, instruction->base.source_node, base_ptr);
19672 result->value.type = type_entry->data.error_union.err_set_type;
19673 return result;
1950319674}
1950419675
1950519676static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
......@@ -19515,48 +19686,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
1951519686 assert(ptr_type->id == ZigTypeIdPointer);
1951619687
1951719688 ZigType *type_entry = ptr_type->data.pointer.child_type;
19518 if (type_is_invalid(type_entry)) {
19689 if (type_is_invalid(type_entry))
1951919690 return ira->codegen->invalid_instruction;
19520 } else if (type_entry->id == ZigTypeIdErrorUnion) {
19521 ZigType *payload_type = type_entry->data.error_union.payload_type;
19522 if (type_is_invalid(payload_type)) {
19523 return ira->codegen->invalid_instruction;
19524 }
19525 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
19526 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19527 PtrLenSingle, 0, 0, 0);
19528 if (instr_is_comptime(value)) {
19529 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19530 if (!ptr_val)
19531 return ira->codegen->invalid_instruction;
19532 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19533 if (err_union_val == nullptr)
19534 return ira->codegen->invalid_instruction;
19535 if (err_union_val->special != ConstValSpecialRuntime) {
19536 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
19537 if (err != nullptr) {
19538 ir_add_error(ira, &instruction->base,
19539 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
19540 return ira->codegen->invalid_instruction;
19541 }
1954219691
19543 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
19544 result->value.data.x_ptr.special = ConstPtrSpecialRef;
19545 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
19546 return result;
19547 }
19548 }
19549
19550 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
19551 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
19552 result->value.type = result_type;
19553 return result;
19554 } else {
19692 if (type_entry->id != ZigTypeIdErrorUnion) {
1955519693 ir_add_error(ira, value,
1955619694 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
1955719695 return ira->codegen->invalid_instruction;
1955819696 }
1955919697
19698 ZigType *payload_type = type_entry->data.error_union.payload_type;
19699 if (type_is_invalid(payload_type))
19700 return ira->codegen->invalid_instruction;
19701
19702 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
19703 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19704 PtrLenSingle, 0, 0, 0);
19705 if (instr_is_comptime(value)) {
19706 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19707 if (!ptr_val)
19708 return ira->codegen->invalid_instruction;
19709 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19710 if (err_union_val == nullptr)
19711 return ira->codegen->invalid_instruction;
19712 if (err_union_val->special != ConstValSpecialRuntime) {
19713 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19714 if (err != nullptr) {
19715 ir_add_error(ira, &instruction->base,
19716 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
19717 return ira->codegen->invalid_instruction;
19718 }
19719
19720 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
19721 result->value.data.x_ptr.special = ConstPtrSpecialRef;
19722 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
19723 return result;
19724 }
19725 }
19726
19727 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
19728 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
19729 result->value.type = result_type;
19730 return result;
1956019731}
1956119732
1956219733static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
......@@ -19973,7 +20144,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
1997320144 return ira->codegen->invalid_instruction;
1997420145 }
1997520146
19976 IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type);
20147 IrInstruction *result = ir_const(ira, target, result_type);
1997720148 copy_const_val(&result->value, val, false);
1997820149 result->value.type = result_type;
1997920150 return result;
......@@ -20021,8 +20192,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2002120192 if (!val)
2002220193 return ira->codegen->invalid_instruction;
2002320194
20024 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node,
20025 dest_type);
20195 IrInstruction *result = ir_const(ira, source_instr, dest_type);
2002620196 copy_const_val(&result->value, val, false);
2002720197 result->value.type = dest_type;
2002820198 return result;
......@@ -20045,9 +20215,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2004520215 return ira->codegen->invalid_instruction;
2004620216 }
2004720217
20048 IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope,
20049 source_instr->source_node, nullptr, ptr);
20050 casted_ptr->value.type = dest_type;
20218 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr);
2005120219
2005220220 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
2005320221 ErrorMsg *msg = ir_add_error(ira, source_instr,
......@@ -20073,7 +20241,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2007320241 return result;
2007420242}
2007520243
20076static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {
20244static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) {
2007720245 IrInstruction *dest_type_value = instruction->dest_type->child;
2007820246 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
2007920247 if (type_is_invalid(dest_type))
......@@ -20211,15 +20379,29 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2021120379 if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
2021220380 return err;
2021320381 }
20214 break;
20382 return ErrorNone;
2021520383 case ConstArraySpecialUndef:
2021620384 zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
2021720385 case ConstArraySpecialBuf:
2021820386 zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
2021920387 }
20220
20221 return ErrorNone;
20388 zig_unreachable();
2022220389 }
20390 case ZigTypeIdEnum:
20391 switch (val->type->data.enumeration.layout) {
20392 case ContainerLayoutAuto:
20393 zig_panic("TODO buf_read_value_bytes enum auto");
20394 case ContainerLayoutPacked:
20395 zig_panic("TODO buf_read_value_bytes enum packed");
20396 case ContainerLayoutExtern: {
20397 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
20398 assert(tag_int_type->id == ZigTypeIdInt);
20399 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
20400 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
20401 return ErrorNone;
20402 }
20403 }
20404 zig_unreachable();
2022320405 case ZigTypeIdStruct:
2022420406 switch (val->type->data.structure.layout) {
2022520407 case ContainerLayoutAuto: {
......@@ -20258,8 +20440,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2025820440 zig_panic("TODO buf_read_value_bytes error union");
2025920441 case ZigTypeIdErrorSet:
2026020442 zig_panic("TODO buf_read_value_bytes pure error type");
20261 case ZigTypeIdEnum:
20262 zig_panic("TODO buf_read_value_bytes enum type");
2026320443 case ZigTypeIdFn:
2026420444 zig_panic("TODO buf_read_value_bytes fn type");
2026520445 case ZigTypeIdUnion:
......@@ -20426,8 +20606,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2042620606 case TldIdContainer:
2042720607 case TldIdCompTime:
2042820608 zig_unreachable();
20429 case TldIdVar:
20430 {
20609 case TldIdVar: {
2043120610 TldVar *tld_var = (TldVar *)tld;
2043220611 ZigVar *var = tld_var->var;
2043320612
......@@ -20445,8 +20624,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2044520624 return ir_get_deref(ira, &instruction->base, var_ptr);
2044620625 }
2044720626 }
20448 case TldIdFn:
20449 {
20627 case TldIdFn: {
2045020628 TldFn *tld_fn = (TldFn *)tld;
2045120629 ZigFn *fn_entry = tld_fn->fn_entry;
2045220630 assert(fn_entry->type_entry);
......@@ -20492,8 +20670,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
2049220670 if (!val)
2049320671 return ira->codegen->invalid_instruction;
2049420672 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
20495 IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope,
20496 instruction->base.source_node, usize);
20673 IrInstruction *result = ir_const(ira, &instruction->base, usize);
2049720674 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
2049820675 result->value.type = usize;
2049920676 return result;
......@@ -21331,6 +21508,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2133121508 case IrInstructionIdErrWrapCode:
2133221509 case IrInstructionIdErrWrapPayload:
2133321510 case IrInstructionIdCast:
21511 case IrInstructionIdDeclVarGen:
21512 case IrInstructionIdPtrCastGen:
21513 case IrInstructionIdCmpxchgGen:
2133421514 zig_unreachable();
2133521515
2133621516 case IrInstructionIdReturn:
......@@ -21341,8 +21521,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2134121521 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
2134221522 case IrInstructionIdBinOp:
2134321523 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
21344 case IrInstructionIdDeclVar:
21345 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);
21524 case IrInstructionIdDeclVarSrc:
21525 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction);
2134621526 case IrInstructionIdLoadPtr:
2134721527 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
2134821528 case IrInstructionIdStorePtr:
......@@ -21387,8 +21567,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2138721567 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
2138821568 case IrInstructionIdTestNonNull:
2138921569 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);
21390 case IrInstructionIdUnwrapOptional:
21391 return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction);
21570 case IrInstructionIdOptionalUnwrapPtr:
21571 return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction);
2139221572 case IrInstructionIdClz:
2139321573 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
2139421574 case IrInstructionIdCtz:
......@@ -21429,8 +21609,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2142921609 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
2143021610 case IrInstructionIdEmbedFile:
2143121611 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
21432 case IrInstructionIdCmpxchg:
21433 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction);
21612 case IrInstructionIdCmpxchgSrc:
21613 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction);
2143421614 case IrInstructionIdFence:
2143521615 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);
2143621616 case IrInstructionIdTruncate:
......@@ -21497,8 +21677,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2149721677 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
2149821678 case IrInstructionIdPanic:
2149921679 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
21500 case IrInstructionIdPtrCast:
21501 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction);
21680 case IrInstructionIdPtrCastSrc:
21681 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
2150221682 case IrInstructionIdBitCast:
2150321683 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
2150421684 case IrInstructionIdIntToPtr:
......@@ -21682,7 +21862,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2168221862 case IrInstructionIdBr:
2168321863 case IrInstructionIdCondBr:
2168421864 case IrInstructionIdSwitchBr:
21685 case IrInstructionIdDeclVar:
21865 case IrInstructionIdDeclVarSrc:
21866 case IrInstructionIdDeclVarGen:
2168621867 case IrInstructionIdStorePtr:
2168721868 case IrInstructionIdCall:
2168821869 case IrInstructionIdReturn:
......@@ -21697,7 +21878,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2169721878 case IrInstructionIdCInclude:
2169821879 case IrInstructionIdCDefine:
2169921880 case IrInstructionIdCUndef:
21700 case IrInstructionIdCmpxchg:
2170121881 case IrInstructionIdFence:
2170221882 case IrInstructionIdMemset:
2170321883 case IrInstructionIdMemcpy:
......@@ -21725,6 +21905,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2172521905 case IrInstructionIdMergeErrRetTraces:
2172621906 case IrInstructionIdMarkErrRetTracePtr:
2172721907 case IrInstructionIdAtomicRmw:
21908 case IrInstructionIdCmpxchgGen:
21909 case IrInstructionIdCmpxchgSrc:
2172821910 return true;
2172921911
2173021912 case IrInstructionIdPhi:
......@@ -21750,7 +21932,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2175021932 case IrInstructionIdSliceType:
2175121933 case IrInstructionIdSizeOf:
2175221934 case IrInstructionIdTestNonNull:
21753 case IrInstructionIdUnwrapOptional:
21935 case IrInstructionIdOptionalUnwrapPtr:
2175421936 case IrInstructionIdClz:
2175521937 case IrInstructionIdCtz:
2175621938 case IrInstructionIdPopCount:
......@@ -21777,7 +21959,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2177721959 case IrInstructionIdErrWrapPayload:
2177821960 case IrInstructionIdFnProto:
2177921961 case IrInstructionIdTestComptime:
21780 case IrInstructionIdPtrCast:
21962 case IrInstructionIdPtrCastSrc:
21963 case IrInstructionIdPtrCastGen:
2178121964 case IrInstructionIdBitCast:
2178221965 case IrInstructionIdWidenOrShorten:
2178321966 case IrInstructionIdPtrToInt:
src/ir.hpp+1-1
......@@ -13,7 +13,7 @@
1313bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
1414bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
1515
16IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
1717 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
1818 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
1919 IrExecutable *parent_exec);
src/ir_print.cpp+61-22
......@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
172172 }
173173}
174174
175static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {
175static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) {
176176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
177177 const char *name = buf_ptr(&decl_var_instruction->var->name);
178178 if (decl_var_instruction->var_type) {
......@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
332332}
333333
334334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
335 fprintf(irp->f, "*");
336335 ir_print_other_instruction(irp, instruction->ptr);
336 fprintf(irp->f, ".*");
337337}
338338
339339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
......@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
479479 fprintf(irp->f, ")");
480480}
481481
482static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
483 fprintf(irp->f, "*");
482static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
484483 ir_print_other_instruction(irp, instruction->value);
485484 fprintf(irp->f, " != null");
486485}
487486
488static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {
489 fprintf(irp->f, "&??*");
490 ir_print_other_instruction(irp, instruction->value);
487static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) {
488 fprintf(irp->f, "&");
489 ir_print_other_instruction(irp, instruction->base_ptr);
490 fprintf(irp->f, ".*.?");
491491 if (!instruction->safety_check_on) {
492492 fprintf(irp->f, " // no safety");
493493 }
......@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio
613613 fprintf(irp->f, ")");
614614}
615615
616static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
616static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) {
617617 fprintf(irp->f, "@cmpxchg(");
618618 ir_print_other_instruction(irp, instruction->ptr);
619619 fprintf(irp->f, ", ");
......@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
627627 fprintf(irp->f, ")");
628628}
629629
630static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
631 fprintf(irp->f, "@cmpxchg(");
632 ir_print_other_instruction(irp, instruction->ptr);
633 fprintf(irp->f, ", ");
634 ir_print_other_instruction(irp, instruction->cmp_value);
635 fprintf(irp->f, ", ");
636 ir_print_other_instruction(irp, instruction->new_value);
637 fprintf(irp->f, ", TODO print atomic orders)");
638}
639
630640static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
631641 fprintf(irp->f, "@fence(");
632642 ir_print_other_instruction(irp, instruction->order_value);
......@@ -820,13 +830,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
820830}
821831
822832static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
823 fprintf(irp->f, "@unwrapErrorCode(");
824 ir_print_other_instruction(irp, instruction->value);
833 fprintf(irp->f, "UnwrapErrorCode(");
834 ir_print_other_instruction(irp, instruction->err_union);
825835 fprintf(irp->f, ")");
826836}
827837
828838static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
829 fprintf(irp->f, "@unwrapErrorPayload(");
839 fprintf(irp->f, "ErrorUnionFieldPayload(");
830840 ir_print_other_instruction(irp, instruction->value);
831841 fprintf(irp->f, ")");
832842 if (!instruction->safety_check_on) {
......@@ -879,7 +889,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
879889 fprintf(irp->f, ")");
880890}
881891
882static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
892static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) {
883893 fprintf(irp->f, "@ptrCast(");
884894 if (instruction->dest_type) {
885895 ir_print_other_instruction(irp, instruction->dest_type);
......@@ -889,6 +899,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
889899 fprintf(irp->f, ")");
890900}
891901
902static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) {
903 fprintf(irp->f, "@ptrCast(");
904 ir_print_other_instruction(irp, instruction->ptr);
905 fprintf(irp->f, ")");
906}
907
892908static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
893909 fprintf(irp->f, "@bitCast(");
894910 if (instruction->dest_type) {
......@@ -900,7 +916,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
900916}
901917
902918static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
903 fprintf(irp->f, "@widenOrShorten(");
919 fprintf(irp->f, "WidenOrShorten(");
904920 ir_print_other_instruction(irp, instruction->target);
905921 fprintf(irp->f, ")");
906922}
......@@ -1323,6 +1339,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
13231339 fprintf(irp->f, ")");
13241340}
13251341
1342static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) {
1343 ZigVar *var = decl_var_instruction->var;
1344 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
1345 const char *name = buf_ptr(&decl_var_instruction->var->name);
1346 fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
1347 var->align_bytes);
1348
1349 ir_print_other_instruction(irp, decl_var_instruction->init_value);
1350 if (decl_var_instruction->var->is_comptime != nullptr) {
1351 fprintf(irp->f, " // comptime = ");
1352 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
1353 }
1354}
1355
13261356static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
13271357 fprintf(irp->f, "@bswap(");
13281358 if (instruction->type != nullptr) {
......@@ -1361,8 +1391,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
13611391 case IrInstructionIdBinOp:
13621392 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
13631393 break;
1364 case IrInstructionIdDeclVar:
1365 ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);
1394 case IrInstructionIdDeclVarSrc:
1395 ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
13661396 break;
13671397 case IrInstructionIdCast:
13681398 ir_print_cast(irp, (IrInstructionCast *)instruction);
......@@ -1452,10 +1482,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
14521482 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
14531483 break;
14541484 case IrInstructionIdTestNonNull:
1455 ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);
1485 ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction);
14561486 break;
1457 case IrInstructionIdUnwrapOptional:
1458 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);
1487 case IrInstructionIdOptionalUnwrapPtr:
1488 ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
14591489 break;
14601490 case IrInstructionIdCtz:
14611491 ir_print_ctz(irp, (IrInstructionCtz *)instruction);
......@@ -1508,8 +1538,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15081538 case IrInstructionIdEmbedFile:
15091539 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
15101540 break;
1511 case IrInstructionIdCmpxchg:
1512 ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);
1541 case IrInstructionIdCmpxchgSrc:
1542 ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction);
1543 break;
1544 case IrInstructionIdCmpxchgGen:
1545 ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction);
15131546 break;
15141547 case IrInstructionIdFence:
15151548 ir_print_fence(irp, (IrInstructionFence *)instruction);
......@@ -1607,8 +1640,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
16071640 case IrInstructionIdTestComptime:
16081641 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
16091642 break;
1610 case IrInstructionIdPtrCast:
1611 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
1643 case IrInstructionIdPtrCastSrc:
1644 ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction);
1645 break;
1646 case IrInstructionIdPtrCastGen:
1647 ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
16121648 break;
16131649 case IrInstructionIdBitCast:
16141650 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
......@@ -1775,6 +1811,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
17751811 case IrInstructionIdCheckRuntimeScope:
17761812 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
17771813 break;
1814 case IrInstructionIdDeclVarGen:
1815 ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction);
1816 break;
17781817 }
17791818 fprintf(irp->f, "\n");
17801819}
src/parser.cpp+4-4
......@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse
381381 else_body = ast_expect(pc, body_parser);
382382 }
383383
384 assert(res->type == NodeTypeTestExpr);
384 assert(res->type == NodeTypeIfOptional);
385385 if (err_payload != nullptr) {
386386 AstNodeTestExpr old = res->data.test_expr;
387387 res->type = NodeTypeIfErrorExpr;
......@@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
990990 if (requires_semi && else_body == nullptr)
991991 expect_token(pc, TokenIdSemicolon);
992992
993 assert(res->type == NodeTypeTestExpr);
993 assert(res->type == NodeTypeIfOptional);
994994 if (err_payload != nullptr) {
995995 AstNodeTestExpr old = res->data.test_expr;
996996 res->type = NodeTypeIfErrorExpr;
......@@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {
22042204 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
22052205
22062206 PtrPayload payload;
2207 AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first);
2207 AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
22082208 res->data.test_expr.target_node = condition;
22092209 if (opt_payload.unwrap(&payload)) {
22102210 res->data.test_expr.var_symbol = token_buf(payload.payload);
......@@ -2999,7 +2999,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
29992999 visit_field(&node->data.if_err_expr.then_node, visit, context);
30003000 visit_field(&node->data.if_err_expr.else_node, visit, context);
30013001 break;
3002 case NodeTypeTestExpr:
3002 case NodeTypeIfOptional:
30033003 visit_field(&node->data.test_expr.target_node, visit, context);
30043004 visit_field(&node->data.test_expr.then_node, visit, context);
30053005 visit_field(&node->data.test_expr.else_node, visit, context);
std/event/fs.zig+23-26
......@@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type {
13071307
13081308const test_tmp_dir = "std_event_fs_test";
13091309
1310test "write a file, watch it, write it again" {
1311 if (builtin.os == builtin.Os.windows) {
1312 // TODO this test is disabled on windows until the coroutine rewrite is finished.
1313 // https://github.com/ziglang/zig/issues/1363
1314 return error.SkipZigTest;
1315 }
1316 var da = std.heap.DirectAllocator.init();
1317 defer da.deinit();
1318
1319 const allocator = &da.allocator;
1320
1321 // TODO move this into event loop too
1322 try os.makePath(allocator, test_tmp_dir);
1323 defer os.deleteTree(allocator, test_tmp_dir) catch {};
1324
1325 var loop: Loop = undefined;
1326 try loop.initMultiThreaded(allocator);
1327 defer loop.deinit();
1328
1329 var result: anyerror!void = error.ResultNeverWritten;
1330 const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
1331 defer cancel handle;
1332
1333 loop.run();
1334 return result;
1335}
1310// TODO this test is disabled until the coroutine rewrite is finished.
1311//test "write a file, watch it, write it again" {
1312// return error.SkipZigTest;
1313// var da = std.heap.DirectAllocator.init();
1314// defer da.deinit();
1315//
1316// const allocator = &da.allocator;
1317//
1318// // TODO move this into event loop too
1319// try os.makePath(allocator, test_tmp_dir);
1320// defer os.deleteTree(allocator, test_tmp_dir) catch {};
1321//
1322// var loop: Loop = undefined;
1323// try loop.initMultiThreaded(allocator);
1324// defer loop.deinit();
1325//
1326// var result: anyerror!void = error.ResultNeverWritten;
1327// const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
1328// defer cancel handle;
1329//
1330// loop.run();
1331// return result;
1332//}
13361333
13371334async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
13381335 result.* = await (async testFsWatch(loop) catch unreachable);
test/behavior.zig deleted-82
......@@ -1,82 +0,0 @@
1const builtin = @import("builtin");
2
3comptime {
4 _ = @import("cases/align.zig");
5 _ = @import("cases/alignof.zig");
6 _ = @import("cases/array.zig");
7 _ = @import("cases/asm.zig");
8 _ = @import("cases/atomics.zig");
9 _ = @import("cases/bitcast.zig");
10 _ = @import("cases/bool.zig");
11 _ = @import("cases/bswap.zig");
12 _ = @import("cases/bitreverse.zig");
13 _ = @import("cases/bugs/1076.zig");
14 _ = @import("cases/bugs/1111.zig");
15 _ = @import("cases/bugs/1277.zig");
16 _ = @import("cases/bugs/1322.zig");
17 _ = @import("cases/bugs/1381.zig");
18 _ = @import("cases/bugs/1421.zig");
19 _ = @import("cases/bugs/1442.zig");
20 _ = @import("cases/bugs/1486.zig");
21 _ = @import("cases/bugs/394.zig");
22 _ = @import("cases/bugs/655.zig");
23 _ = @import("cases/bugs/656.zig");
24 _ = @import("cases/bugs/726.zig");
25 _ = @import("cases/bugs/828.zig");
26 _ = @import("cases/bugs/920.zig");
27 _ = @import("cases/byval_arg_var.zig");
28 _ = @import("cases/cancel.zig");
29 _ = @import("cases/cast.zig");
30 _ = @import("cases/const_slice_child.zig");
31 _ = @import("cases/coroutine_await_struct.zig");
32 _ = @import("cases/coroutines.zig");
33 _ = @import("cases/defer.zig");
34 _ = @import("cases/enum.zig");
35 _ = @import("cases/enum_with_members.zig");
36 _ = @import("cases/error.zig");
37 _ = @import("cases/eval.zig");
38 _ = @import("cases/field_parent_ptr.zig");
39 _ = @import("cases/fn.zig");
40 _ = @import("cases/fn_in_struct_in_comptime.zig");
41 _ = @import("cases/for.zig");
42 _ = @import("cases/generics.zig");
43 _ = @import("cases/if.zig");
44 _ = @import("cases/import.zig");
45 _ = @import("cases/incomplete_struct_param_tld.zig");
46 _ = @import("cases/inttoptr.zig");
47 _ = @import("cases/ir_block_deps.zig");
48 _ = @import("cases/math.zig");
49 _ = @import("cases/merge_error_sets.zig");
50 _ = @import("cases/misc.zig");
51 _ = @import("cases/namespace_depends_on_compile_var/index.zig");
52 _ = @import("cases/new_stack_call.zig");
53 _ = @import("cases/null.zig");
54 _ = @import("cases/optional.zig");
55 _ = @import("cases/pointers.zig");
56 _ = @import("cases/popcount.zig");
57 _ = @import("cases/ptrcast.zig");
58 _ = @import("cases/pub_enum/index.zig");
59 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
60 _ = @import("cases/reflection.zig");
61 _ = @import("cases/sizeof_and_typeof.zig");
62 _ = @import("cases/slice.zig");
63 _ = @import("cases/struct.zig");
64 _ = @import("cases/struct_contains_null_ptr_itself.zig");
65 _ = @import("cases/struct_contains_slice_of_itself.zig");
66 _ = @import("cases/switch.zig");
67 _ = @import("cases/switch_prong_err_enum.zig");
68 _ = @import("cases/switch_prong_implicit_cast.zig");
69 _ = @import("cases/syntax.zig");
70 _ = @import("cases/this.zig");
71 _ = @import("cases/truncate.zig");
72 _ = @import("cases/try.zig");
73 _ = @import("cases/type_info.zig");
74 _ = @import("cases/undefined.zig");
75 _ = @import("cases/underscore.zig");
76 _ = @import("cases/union.zig");
77 _ = @import("cases/var_args.zig");
78 _ = @import("cases/void.zig");
79 _ = @import("cases/while.zig");
80 _ = @import("cases/widening.zig");
81 _ = @import("cases/bit_shifting.zig");
82}
test/cases/align.zig deleted-230
......@@ -1,230 +0,0 @@
1const assert = @import("std").debug.assert;
2const builtin = @import("builtin");
3
4var foo: u8 align(4) = 100;
5
6test "global variable alignment" {
7 assert(@typeOf(&foo).alignment == 4);
8 assert(@typeOf(&foo) == *align(4) u8);
9 const slice = (*[1]u8)(&foo)[0..];
10 assert(@typeOf(slice) == []align(4) u8);
11}
12
13fn derp() align(@sizeOf(usize) * 2) i32 {
14 return 1234;
15}
16fn noop1() align(1) void {}
17fn noop4() align(4) void {}
18
19test "function alignment" {
20 assert(derp() == 1234);
21 assert(@typeOf(noop1) == fn () align(1) void);
22 assert(@typeOf(noop4) == fn () align(4) void);
23 noop1();
24 noop4();
25}
26
27var baz: packed struct {
28 a: u32,
29 b: u32,
30} = undefined;
31
32test "packed struct alignment" {
33 assert(@typeOf(&baz.b) == *align(1) u32);
34}
35
36const blah: packed struct {
37 a: u3,
38 b: u3,
39 c: u2,
40} = undefined;
41
42test "bit field alignment" {
43 assert(@typeOf(&blah.b) == *align(1:3:1) const u3);
44}
45
46test "default alignment allows unspecified in type syntax" {
47 assert(*u32 == *align(@alignOf(u32)) u32);
48}
49
50test "implicitly decreasing pointer alignment" {
51 const a: u32 align(4) = 3;
52 const b: u32 align(8) = 4;
53 assert(addUnaligned(&a, &b) == 7);
54}
55
56fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
57 return a.* + b.*;
58}
59
60test "implicitly decreasing slice alignment" {
61 const a: u32 align(4) = 3;
62 const b: u32 align(8) = 4;
63 assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
64}
65fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
66 return a[0] + b[0];
67}
68
69test "specifying alignment allows pointer cast" {
70 testBytesAlign(0x33);
71}
72fn testBytesAlign(b: u8) void {
73 var bytes align(4) = []u8{
74 b,
75 b,
76 b,
77 b,
78 };
79 const ptr = @ptrCast(*u32, &bytes[0]);
80 assert(ptr.* == 0x33333333);
81}
82
83test "specifying alignment allows slice cast" {
84 testBytesAlignSlice(0x33);
85}
86fn testBytesAlignSlice(b: u8) void {
87 var bytes align(4) = []u8{
88 b,
89 b,
90 b,
91 b,
92 };
93 const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
94 assert(slice[0] == 0x33333333);
95}
96
97test "@alignCast pointers" {
98 var x: u32 align(4) = 1;
99 expectsOnly1(&x);
100 assert(x == 2);
101}
102fn expectsOnly1(x: *align(1) u32) void {
103 expects4(@alignCast(4, x));
104}
105fn expects4(x: *align(4) u32) void {
106 x.* += 1;
107}
108
109test "@alignCast slices" {
110 var array align(4) = []u32{
111 1,
112 1,
113 };
114 const slice = array[0..];
115 sliceExpectsOnly1(slice);
116 assert(slice[0] == 2);
117}
118fn sliceExpectsOnly1(slice: []align(1) u32) void {
119 sliceExpects4(@alignCast(4, slice));
120}
121fn sliceExpects4(slice: []align(4) u32) void {
122 slice[0] += 1;
123}
124
125test "implicitly decreasing fn alignment" {
126 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
127 testImplicitlyDecreaseFnAlign(alignedBig, 5678);
128}
129
130fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
131 assert(ptr() == answer);
132}
133
134fn alignedSmall() align(8) i32 {
135 return 1234;
136}
137fn alignedBig() align(16) i32 {
138 return 5678;
139}
140
141test "@alignCast functions" {
142 assert(fnExpectsOnly1(simple4) == 0x19);
143}
144fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
145 return fnExpects4(@alignCast(4, ptr));
146}
147fn fnExpects4(ptr: fn () align(4) i32) i32 {
148 return ptr();
149}
150fn simple4() align(4) i32 {
151 return 0x19;
152}
153
154test "generic function with align param" {
155 assert(whyWouldYouEverDoThis(1) == 0x1);
156 assert(whyWouldYouEverDoThis(4) == 0x1);
157 assert(whyWouldYouEverDoThis(8) == 0x1);
158}
159
160fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
161 return 0x1;
162}
163
164test "@ptrCast preserves alignment of bigger source" {
165 var x: u32 align(16) = 1234;
166 const ptr = @ptrCast(*u8, &x);
167 assert(@typeOf(ptr) == *align(16) u8);
168}
169
170test "runtime known array index has best alignment possible" {
171 // take full advantage of over-alignment
172 var array align(4) = []u8{ 1, 2, 3, 4 };
173 assert(@typeOf(&array[0]) == *align(4) u8);
174 assert(@typeOf(&array[1]) == *u8);
175 assert(@typeOf(&array[2]) == *align(2) u8);
176 assert(@typeOf(&array[3]) == *u8);
177
178 // because align is too small but we still figure out to use 2
179 var bigger align(2) = []u64{ 1, 2, 3, 4 };
180 assert(@typeOf(&bigger[0]) == *align(2) u64);
181 assert(@typeOf(&bigger[1]) == *align(2) u64);
182 assert(@typeOf(&bigger[2]) == *align(2) u64);
183 assert(@typeOf(&bigger[3]) == *align(2) u64);
184
185 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
186 var smaller align(2) = []u32{ 1, 2, 3, 4 };
187 comptime assert(@typeOf(smaller[0..]) == []align(2) u32);
188 comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
189 testIndex(smaller[0..].ptr, 0, *align(2) u32);
190 testIndex(smaller[0..].ptr, 1, *align(2) u32);
191 testIndex(smaller[0..].ptr, 2, *align(2) u32);
192 testIndex(smaller[0..].ptr, 3, *align(2) u32);
193
194 // has to use ABI alignment because index known at runtime only
195 testIndex2(array[0..].ptr, 0, *u8);
196 testIndex2(array[0..].ptr, 1, *u8);
197 testIndex2(array[0..].ptr, 2, *u8);
198 testIndex2(array[0..].ptr, 3, *u8);
199}
200fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
201 comptime assert(@typeOf(&smaller[index]) == T);
202}
203fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
204 comptime assert(@typeOf(&ptr[index]) == T);
205}
206
207test "alignstack" {
208 assert(fnWithAlignedStack() == 1234);
209}
210
211fn fnWithAlignedStack() i32 {
212 @setAlignStack(256);
213 return 1234;
214}
215
216test "alignment of structs" {
217 assert(@alignOf(struct {
218 a: i32,
219 b: *i32,
220 }) == @alignOf(usize));
221}
222
223test "alignment of extern() void" {
224 var runtime_nothing = nothing;
225 const casted1 = @ptrCast(*const u8, runtime_nothing);
226 const casted2 = @ptrCast(extern fn () void, casted1);
227 casted2();
228}
229
230extern fn nothing() void {}
test/cases/alignof.zig deleted-17
......@@ -1,17 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const Foo = struct {
7 x: u32,
8 y: u32,
9 z: u32,
10};
11
12test "@alignOf(T) before referencing T" {
13 comptime assert(@alignOf(Foo) != maxInt(usize));
14 if (builtin.arch == builtin.Arch.x86_64) {
15 comptime assert(@alignOf(Foo) == 4);
16 }
17}
test/cases/array.zig deleted-173
......@@ -1,173 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4test "arrays" {
5 var array: [5]u32 = undefined;
6
7 var i: u32 = 0;
8 while (i < 5) {
9 array[i] = i + 1;
10 i = array[i];
11 }
12
13 i = 0;
14 var accumulator = u32(0);
15 while (i < 5) {
16 accumulator += array[i];
17
18 i += 1;
19 }
20
21 assert(accumulator == 15);
22 assert(getArrayLen(array) == 5);
23}
24fn getArrayLen(a: []const u32) usize {
25 return a.len;
26}
27
28test "void arrays" {
29 var array: [4]void = undefined;
30 array[0] = void{};
31 array[1] = array[2];
32 assert(@sizeOf(@typeOf(array)) == 0);
33 assert(array.len == 4);
34}
35
36test "array literal" {
37 const hex_mult = []u16{
38 4096,
39 256,
40 16,
41 1,
42 };
43
44 assert(hex_mult.len == 4);
45 assert(hex_mult[1] == 256);
46}
47
48test "array dot len const expr" {
49 assert(comptime x: {
50 break :x some_array.len == 4;
51 });
52}
53
54const ArrayDotLenConstExpr = struct {
55 y: [some_array.len]u8,
56};
57const some_array = []u8{
58 0,
59 1,
60 2,
61 3,
62};
63
64test "nested arrays" {
65 const array_of_strings = [][]const u8{
66 "hello",
67 "this",
68 "is",
69 "my",
70 "thing",
71 };
72 for (array_of_strings) |s, i| {
73 if (i == 0) assert(mem.eql(u8, s, "hello"));
74 if (i == 1) assert(mem.eql(u8, s, "this"));
75 if (i == 2) assert(mem.eql(u8, s, "is"));
76 if (i == 3) assert(mem.eql(u8, s, "my"));
77 if (i == 4) assert(mem.eql(u8, s, "thing"));
78 }
79}
80
81var s_array: [8]Sub = undefined;
82const Sub = struct {
83 b: u8,
84};
85const Str = struct {
86 a: []Sub,
87};
88test "set global var array via slice embedded in struct" {
89 var s = Str{ .a = s_array[0..] };
90
91 s.a[0].b = 1;
92 s.a[1].b = 2;
93 s.a[2].b = 3;
94
95 assert(s_array[0].b == 1);
96 assert(s_array[1].b == 2);
97 assert(s_array[2].b == 3);
98}
99
100test "array literal with specified size" {
101 var array = [2]u8{
102 1,
103 2,
104 };
105 assert(array[0] == 1);
106 assert(array[1] == 2);
107}
108
109test "array child property" {
110 var x: [5]i32 = undefined;
111 assert(@typeOf(x).Child == i32);
112}
113
114test "array len property" {
115 var x: [5]i32 = undefined;
116 assert(@typeOf(x).len == 5);
117}
118
119test "array len field" {
120 var arr = [4]u8{ 0, 0, 0, 0 };
121 var ptr = &arr;
122 assert(arr.len == 4);
123 comptime assert(arr.len == 4);
124 assert(ptr.len == 4);
125 comptime assert(ptr.len == 4);
126}
127
128test "single-item pointer to array indexing and slicing" {
129 testSingleItemPtrArrayIndexSlice();
130 comptime testSingleItemPtrArrayIndexSlice();
131}
132
133fn testSingleItemPtrArrayIndexSlice() void {
134 var array = "aaaa";
135 doSomeMangling(&array);
136 assert(mem.eql(u8, "azya", array));
137}
138
139fn doSomeMangling(array: *[4]u8) void {
140 array[1] = 'z';
141 array[2..3][0] = 'y';
142}
143
144test "implicit cast single-item pointer" {
145 testImplicitCastSingleItemPtr();
146 comptime testImplicitCastSingleItemPtr();
147}
148
149fn testImplicitCastSingleItemPtr() void {
150 var byte: u8 = 100;
151 const slice = (*[1]u8)(&byte)[0..];
152 slice[0] += 1;
153 assert(byte == 101);
154}
155
156fn testArrayByValAtComptime(b: [2]u8) u8 {
157 return b[0];
158}
159
160test "comptime evalutating function that takes array by value" {
161 const arr = []u8{ 0, 1 };
162 _ = comptime testArrayByValAtComptime(arr);
163 _ = comptime testArrayByValAtComptime(arr);
164}
165
166test "implicit comptime in array type size" {
167 var arr: [plusOne(10)]bool = undefined;
168 assert(arr.len == 11);
169}
170
171fn plusOne(x: u32) u32 {
172 return x + 1;
173}
test/cases/asm.zig deleted-48
......@@ -1,48 +0,0 @@
1const config = @import("builtin");
2const assert = @import("std").debug.assert;
3
4comptime {
5 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
6 asm volatile (
7 \\.globl aoeu;
8 \\.type aoeu, @function;
9 \\.set aoeu, derp;
10 );
11 }
12}
13
14test "module level assembly" {
15 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
16 assert(aoeu() == 1234);
17 }
18}
19
20test "output constraint modifiers" {
21 // This is only testing compilation.
22 var a: u32 = 3;
23 asm volatile ("" : [_]"=m,r"(a) : : "");
24 asm volatile ("" : [_]"=r,m"(a) : : "");
25}
26
27test "alternative constraints" {
28 // Make sure we allow commas as a separator for alternative constraints.
29 var a: u32 = 3;
30 asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : "");
31}
32
33test "sized integer/float in asm input" {
34 asm volatile ("" : : [_]"m"(usize(3)) : "");
35 asm volatile ("" : : [_]"m"(i15(-3)) : "");
36 asm volatile ("" : : [_]"m"(u3(3)) : "");
37 asm volatile ("" : : [_]"m"(i3(3)) : "");
38 asm volatile ("" : : [_]"m"(u121(3)) : "");
39 asm volatile ("" : : [_]"m"(i121(3)) : "");
40 asm volatile ("" : : [_]"m"(f32(3.17)) : "");
41 asm volatile ("" : : [_]"m"(f64(3.17)) : "");
42}
43
44extern fn aoeu() i32;
45
46export fn derp() i32 {
47 return 1234;
48}
test/cases/atomics.zig deleted-71
......@@ -1,71 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;
6
7test "cmpxchg" {
8 var x: i32 = 1234;
9 if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
10 assert(x1 == 1234);
11 } else {
12 @panic("cmpxchg should have failed");
13 }
14
15 while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
16 assert(x1 == 1234);
17 }
18 assert(x == 5678);
19
20 assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
21 assert(x == 42);
22}
23
24test "fence" {
25 var x: i32 = 1234;
26 @fence(AtomicOrder.SeqCst);
27 x = 5678;
28}
29
30test "atomicrmw and atomicload" {
31 var data: u8 = 200;
32 testAtomicRmw(&data);
33 assert(data == 42);
34 testAtomicLoad(&data);
35}
36
37fn testAtomicRmw(ptr: *u8) void {
38 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
39 assert(prev_value == 200);
40 comptime {
41 var x: i32 = 1234;
42 const y: i32 = 12345;
43 assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
44 assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
45 }
46}
47
48fn testAtomicLoad(ptr: *u8) void {
49 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
50 assert(x == 42);
51}
52
53test "cmpxchg with ptr" {
54 var data1: i32 = 1234;
55 var data2: i32 = 5678;
56 var data3: i32 = 9101;
57 var x: *i32 = &data1;
58 if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
59 assert(x1 == &data1);
60 } else {
61 @panic("cmpxchg should have failed");
62 }
63
64 while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
65 assert(x1 == &data1);
66 }
67 assert(x == &data3);
68
69 assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
70 assert(x == &data2);
71}
test/cases/bit_shifting.zig deleted-88
......@@ -1,88 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 assert(Key == @IntType(false, Key.bit_count));
6 assert(Key.bit_count >= mask_bit_count);
7 const ShardKey = @IntType(false, mask_bit_count);
8 const shift_amount = Key.bit_count - ShardKey.bit_count;
9 return struct {
10 const Self = @This();
11 shards: [1 << ShardKey.bit_count]?*Node,
12
13 pub fn create() Self {
14 return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) };
15 }
16
17 fn getShardKey(key: Key) ShardKey {
18 // https://github.com/ziglang/zig/issues/1544
19 // this special case is needed because you can't u32 >> 32.
20 if (ShardKey == u0) return 0;
21
22 // this can be u1 >> u0
23 const shard_key = key >> shift_amount;
24
25 // TODO: https://github.com/ziglang/zig/issues/1544
26 // This cast could be implicit if we teach the compiler that
27 // u32 >> 30 -> u2
28 return @intCast(ShardKey, shard_key);
29 }
30
31 pub fn put(self: *Self, node: *Node) void {
32 const shard_key = Self.getShardKey(node.key);
33 node.next = self.shards[shard_key];
34 self.shards[shard_key] = node;
35 }
36
37 pub fn get(self: *Self, key: Key) ?*Node {
38 const shard_key = Self.getShardKey(key);
39 var maybe_node = self.shards[shard_key];
40 while (maybe_node) |node| : (maybe_node = node.next) {
41 if (node.key == key) return node;
42 }
43 return null;
44 }
45
46 pub const Node = struct {
47 key: Key,
48 value: V,
49 next: ?*Node,
50
51 pub fn init(self: *Node, key: Key, value: V) void {
52 self.key = key;
53 self.value = value;
54 self.next = null;
55 }
56 };
57 };
58}
59
60test "sharded table" {
61 // realistic 16-way sharding
62 testShardedTable(u32, 4, 8);
63
64 testShardedTable(u5, 0, 32); // ShardKey == u0
65 testShardedTable(u5, 2, 32);
66 testShardedTable(u5, 5, 32);
67
68 testShardedTable(u1, 0, 2);
69 testShardedTable(u1, 1, 2); // this does u1 >> u0
70
71 testShardedTable(u0, 0, 1);
72}
73fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void {
74 const Table = ShardedTable(Key, mask_bit_count, void);
75
76 var table = Table.create();
77 var node_buffer: [node_count]Table.Node = undefined;
78 for (node_buffer) |*node, i| {
79 const key = @intCast(Key, i);
80 assert(table.get(key) == null);
81 node.init(key, {});
82 table.put(node);
83 }
84
85 for (node_buffer) |*node, i| {
86 assert(table.get(@intCast(Key, i)) == node);
87 }
88}
test/cases/bitcast.zig deleted-37
......@@ -1,37 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const maxInt = std.math.maxInt;
4
5test "@bitCast i32 -> u32" {
6 testBitCast_i32_u32();
7 comptime testBitCast_i32_u32();
8}
9
10fn testBitCast_i32_u32() void {
11 assert(conv(-1) == maxInt(u32));
12 assert(conv2(maxInt(u32)) == -1);
13}
14
15fn conv(x: i32) u32 {
16 return @bitCast(u32, x);
17}
18fn conv2(x: u32) i32 {
19 return @bitCast(i32, x);
20}
21
22test "@bitCast extern enum to its integer type" {
23 const SOCK = extern enum {
24 A,
25 B,
26
27 fn testBitCastExternEnum() void {
28 var SOCK_DGRAM = @This().B;
29 var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
30 assert(sock_dgram == 1);
31 }
32 };
33
34 SOCK.testBitCastExternEnum();
35 comptime SOCK.testBitCastExternEnum();
36}
37
test/cases/bitreverse.zig deleted-81
......@@ -1,81 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const minInt = std.math.minInt;
4
5test "@bitreverse" {
6 comptime testBitReverse();
7 testBitReverse();
8}
9
10fn testBitReverse() void {
11 // using comptime_ints, unsigned
12 assert(@bitreverse(u0, 0) == 0);
13 assert(@bitreverse(u5, 0x12) == 0x9);
14 assert(@bitreverse(u8, 0x12) == 0x48);
15 assert(@bitreverse(u16, 0x1234) == 0x2c48);
16 assert(@bitreverse(u24, 0x123456) == 0x6a2c48);
17 assert(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
18 assert(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
19 assert(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 assert(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 assert(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 assert(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 assert(@bitreverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 assert(@bitreverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 assert(@bitreverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 assert(@bitreverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 assert(@bitreverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 assert(@bitreverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 assert(@bitreverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 assert(@bitreverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 assert(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 assert(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 assert(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 assert(@bitreverse(i0, 0) == 0);
50 assert(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8( 0x49)));
51 assert(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16( 0x2c48)));
52 assert(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24( 0x6a2c48)));
53 assert(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32( 0x1e6a2c48)));
54 assert(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40( 0x591e6a2c48)));
55 assert(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48( 0x3d591e6a2c48)));
56 assert(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56( 0x7b3d591e6a2c48)));
57 assert(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64,u64(0x8f7b3d591e6a2c48)));
58 assert(@bitreverse(i128, @bitCast(i128,u128(0x123456789abcdef11121314151617181))) == @bitCast(i128,u128(0x818e868a828c84888f7b3d591e6a2c48)));
59
60 // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
61 var neg5: i5 = minInt(i5) + 1;
62 assert(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
63 var neg8: i8 = -18;
64 assert(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
65 var neg16: i16 = -32694;
66 assert(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
67 var neg24: i24 = -6773785;
68 assert(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
69 var neg32: i32 = -16773785;
70 assert(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
71 var neg40: i40 = minInt(i40) + 12345;
72 assert(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
73 var neg48: i48 = minInt(i48) + 12345;
74 assert(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
75 var neg56: i56 = minInt(i56) + 12345;
76 assert(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
77 var neg64: i64 = minInt(i64) + 12345;
78 assert(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
79 var neg128: i128 = minInt(i128) + 12345;
80 assert(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
81}
test/cases/bool.zig deleted-35
......@@ -1,35 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "bool literals" {
4 assert(true);
5 assert(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 assert(@boolToInt(t) == u32(1));
12 assert(@boolToInt(f) == u32(0));
13 nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) void {
17 assert(@boolToInt(t) == u32(1));
18 assert(@boolToInt(f) == u32(0));
19}
20
21test "bool cmp" {
22 assert(testBoolCmp(true, false) == false);
23}
24fn testBoolCmp(a: bool, b: bool) bool {
25 return a == b;
26}
27
28const global_f = false;
29const global_t = true;
30const not_global_f = !global_f;
31const not_global_t = !global_t;
32test "compile time bool not" {
33 assert(not_global_f);
34 assert(!not_global_t);
35}
test/cases/bswap.zig deleted-32
......@@ -1,32 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "@bswap" {
5 comptime testByteSwap();
6 testByteSwap();
7}
8
9fn testByteSwap() void {
10 assert(@bswap(u0, 0) == 0);
11 assert(@bswap(u8, 0x12) == 0x12);
12 assert(@bswap(u16, 0x1234) == 0x3412);
13 assert(@bswap(u24, 0x123456) == 0x563412);
14 assert(@bswap(u32, 0x12345678) == 0x78563412);
15 assert(@bswap(u40, 0x123456789a) == 0x9a78563412);
16 assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
17 assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
20
21 assert(@bswap(i0, 0) == 0);
22 assert(@bswap(i8, -50) == -50);
23 assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
27 assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
32}
test/cases/bugs/1076.zig deleted-16
......@@ -1,16 +0,0 @@
1const std = @import("std");
2const mem = std.mem;
3const assert = std.debug.assert;
4
5test "comptime code should not modify constant data" {
6 testCastPtrOfArrayToSliceAndPtr();
7 comptime testCastPtrOfArrayToSliceAndPtr();
8}
9
10fn testCastPtrOfArrayToSliceAndPtr() void {
11 var array = "aoeu";
12 const x: [*]u8 = &array;
13 x[0] += 1;
14 assert(mem.eql(u8, array[0..], "boeu"));
15}
16
test/cases/bugs/1111.zig deleted-12
......@@ -1,12 +0,0 @@
1const Foo = extern enum {
2 Bar = -1,
3};
4
5test "issue 1111 fixed" {
6 const v = Foo.Bar;
7
8 switch (v) {
9 Foo.Bar => return,
10 else => return,
11 }
12}
test/cases/bugs/1277.zig deleted-15
......@@ -1,15 +0,0 @@
1const std = @import("std");
2
3const S = struct {
4 f: ?fn () i32,
5};
6
7const s = S{ .f = f };
8
9fn f() i32 {
10 return 1234;
11}
12
13test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
14 std.debug.assertOrPanic(s.f.?() == 1234);
15}
test/cases/bugs/1322.zig deleted-19
......@@ -1,19 +0,0 @@
1const std = @import("std");
2
3const B = union(enum) {
4 c: C,
5 None,
6};
7
8const A = struct {
9 b: B,
10};
11
12const C = struct {};
13
14test "tagged union with all void fields but a meaningful tag" {
15 var a: A = A{ .b = B{ .c = C{} } };
16 std.debug.assert(@TagType(B)(a.b) == @TagType(B).c);
17 a = A{ .b = B.None };
18 std.debug.assert(@TagType(B)(a.b) == @TagType(B).None);
19}
test/cases/bugs/1381.zig deleted-21
......@@ -1,21 +0,0 @@
1const std = @import("std");
2
3const B = union(enum) {
4 D: u8,
5 E: u16,
6};
7
8const A = union(enum) {
9 B: B,
10 C: u8,
11};
12
13test "union that needs padding bytes inside an array" {
14 var as = []A{
15 A{ .B = B{ .D = 1 } },
16 A{ .B = B{ .D = 1 } },
17 };
18
19 const a = as[0].B;
20 std.debug.assertOrPanic(a.D == 1);
21}
test/cases/bugs/1421.zig deleted-14
......@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5const S = struct {
6 fn method() builtin.TypeInfo {
7 return @typeInfo(S);
8 }
9};
10
11test "functions with return type required to be comptime are generic" {
12 const ti = S.method();
13 assert(builtin.TypeId(ti) == builtin.TypeId.Struct);
14}
test/cases/bugs/1442.zig deleted-11
......@@ -1,11 +0,0 @@
1const std = @import("std");
2
3const Union = union(enum) {
4 Text: []const u8,
5 Color: u32,
6};
7
8test "const error union field alignment" {
9 var union_or_err: anyerror!Union = Union{ .Color = 1234 };
10 std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
11}
test/cases/bugs/1486.zig deleted-11
......@@ -1,11 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 assert(&global == ptr);
9 assert(ptr.* == 1234);
10}
11
test/cases/bugs/394.zig deleted-18
......@@ -1,18 +0,0 @@
1const E = union(enum) {
2 A: [9]u8,
3 B: u64,
4};
5const S = struct {
6 x: u8,
7 y: E,
8};
9
10const assert = @import("std").debug.assert;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 assert(x.x == 3);
18}
test/cases/bugs/655.zig deleted-12
......@@ -1,12 +0,0 @@
1const std = @import("std");
2const other_file = @import("655_other_file.zig");
3
4test "function with *const parameter with type dereferenced by namespace" {
5 const x: other_file.Integer = 1234;
6 comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer);
7 foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) void {
11 std.debug.assert(x.* == 1234);
12}
test/cases/bugs/655_other_file.zig deleted-1
......@@ -1 +0,0 @@
1pub const Integer = u32;
test/cases/bugs/656.zig deleted-31
......@@ -1,31 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const PrefixOp = union(enum) {
4 Return,
5 AddrOf: Value,
6};
7
8const Value = struct {
9 align_expr: ?u32,
10};
11
12test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
13 foo(false, true);
14}
15
16fn foo(a: bool, b: bool) void {
17 var prefix_op = PrefixOp{
18 .AddrOf = Value{ .align_expr = 1234 },
19 };
20 if (a) {} else {
21 switch (prefix_op) {
22 PrefixOp.AddrOf => |addr_of_info| {
23 if (b) {}
24 if (addr_of_info.align_expr) |align_expr| {
25 assert(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/cases/bugs/726.zig deleted-16
......@@ -1,16 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 assert(x.?.* == 4);
7}
8
9test "@ptrCast from var in empty struct to nullable" {
10 const container = struct {
11 var c: u8 = 4;
12 };
13 var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
14 assert(x.?.* == 4);
15}
16
test/cases/bugs/828.zig deleted-33
......@@ -1,33 +0,0 @@
1const CountBy = struct {
2 a: usize,
3
4 const One = CountBy{ .a = 1 };
5
6 pub fn counter(self: *const CountBy) Counter {
7 return Counter{ .i = 0 };
8 }
9};
10
11const Counter = struct {
12 i: usize,
13
14 pub fn count(self: *Counter) bool {
15 self.i += 1;
16 return self.i <= 10;
17 }
18};
19
20fn constCount(comptime cb: *const CountBy, comptime unused: u32) void {
21 comptime {
22 var cnt = cb.counter();
23 if (cnt.i != 0) @compileError("Counter instance reused!");
24 while (cnt.count()) {}
25 }
26}
27
28test "comptime struct return should not return the same instance" {
29 //the first parameter must be passed by reference to trigger the bug
30 //a second parameter is required to trigger the bug
31 const ValA = constCount(&CountBy.One, 12);
32 const ValB = constCount(&CountBy.One, 15);
33}
test/cases/bugs/920.zig deleted-65
......@@ -1,65 +0,0 @@
1const std = @import("std");
2const math = std.math;
3const Random = std.rand.Random;
4
5const ZigTable = struct {
6 r: f64,
7 x: [257]f64,
8 f: [257]f64,
9
10 pdf: fn (f64) f64,
11 is_symmetric: bool,
12 zero_case: fn (*Random, f64) f64,
13};
14
15fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable {
16 var tables: ZigTable = undefined;
17
18 tables.is_symmetric = is_symmetric;
19 tables.r = r;
20 tables.pdf = f;
21 tables.zero_case = zero_case;
22
23 tables.x[0] = v / f(r);
24 tables.x[1] = r;
25
26 for (tables.x[2..256]) |*entry, i| {
27 const last = tables.x[2 + i - 1];
28 entry.* = f_inv(v / last + f(last));
29 }
30 tables.x[256] = 0;
31
32 for (tables.f[0..]) |*entry, i| {
33 entry.* = f(tables.x[i]);
34 }
35
36 return tables;
37}
38
39const norm_r = 3.6541528853610088;
40const norm_v = 0.00492867323399;
41
42fn norm_f(x: f64) f64 {
43 return math.exp(-x * x / 2.0);
44}
45fn norm_f_inv(y: f64) f64 {
46 return math.sqrt(-2.0 * math.ln(y));
47}
48fn norm_zero_case(random: *Random, u: f64) f64 {
49 return 0.0;
50}
51
52const NormalDist = blk: {
53 @setEvalBranchQuota(30000);
54 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
55};
56
57test "bug 920 fixed" {
58 const NormalDist1 = blk: {
59 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
60 };
61
62 for (NormalDist1.f) |_, i| {
63 std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]);
64 }
65}
test/cases/byval_arg_var.zig deleted-27
......@@ -1,27 +0,0 @@
1const std = @import("std");
2
3var result: []const u8 = "wrong";
4
5test "aoeu" {
6 start();
7 blowUpStack(10);
8
9 std.debug.assert(std.mem.eql(u8, result, "string literal"));
10}
11
12fn start() void {
13 foo("string literal");
14}
15
16fn foo(x: var) void {
17 bar(x);
18}
19
20fn bar(x: var) void {
21 result = x;
22}
23
24fn blowUpStack(x: u32) void {
25 if (x == 0) return;
26 blowUpStack(x - 1);
27}
test/cases/cancel.zig deleted-92
......@@ -1,92 +0,0 @@
1const std = @import("std");
2
3var defer_f1: bool = false;
4var defer_f2: bool = false;
5var defer_f3: bool = false;
6
7test "cancel forwards" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = async<&da.allocator> f1() catch unreachable;
12 cancel p;
13 std.debug.assert(defer_f1);
14 std.debug.assert(defer_f2);
15 std.debug.assert(defer_f3);
16}
17
18async fn f1() void {
19 defer {
20 defer_f1 = true;
21 }
22 await (async f2() catch unreachable);
23}
24
25async fn f2() void {
26 defer {
27 defer_f2 = true;
28 }
29 await (async f3() catch unreachable);
30}
31
32async fn f3() void {
33 defer {
34 defer_f3 = true;
35 }
36 suspend;
37}
38
39var defer_b1: bool = false;
40var defer_b2: bool = false;
41var defer_b3: bool = false;
42var defer_b4: bool = false;
43
44test "cancel backwards" {
45 var da = std.heap.DirectAllocator.init();
46 defer da.deinit();
47
48 const p = async<&da.allocator> b1() catch unreachable;
49 cancel p;
50 std.debug.assert(defer_b1);
51 std.debug.assert(defer_b2);
52 std.debug.assert(defer_b3);
53 std.debug.assert(defer_b4);
54}
55
56async fn b1() void {
57 defer {
58 defer_b1 = true;
59 }
60 await (async b2() catch unreachable);
61}
62
63var b4_handle: promise = undefined;
64
65async fn b2() void {
66 const b3_handle = async b3() catch unreachable;
67 resume b4_handle;
68 cancel b4_handle;
69 defer {
70 defer_b2 = true;
71 }
72 const value = await b3_handle;
73 @panic("unreachable");
74}
75
76async fn b3() i32 {
77 defer {
78 defer_b3 = true;
79 }
80 await (async b4() catch unreachable);
81 return 1234;
82}
83
84async fn b4() void {
85 defer {
86 defer_b4 = true;
87 }
88 suspend {
89 b4_handle = @handle();
90 }
91 suspend;
92}
test/cases/cast.zig deleted-472
......@@ -1,472 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5
6test "int to ptr cast" {
7 const x = usize(13);
8 const y = @intToPtr(*u8, x);
9 const z = @ptrToInt(y);
10 assert(z == 13);
11}
12
13test "integer literal to pointer cast" {
14 const vga_mem = @intToPtr(*u16, 0xB8000);
15 assert(@ptrToInt(vga_mem) == 0xB8000);
16}
17
18test "pointer reinterpret const float to int" {
19 const float: f64 = 5.99999999999994648725e-01;
20 const float_ptr = &float;
21 const int_ptr = @ptrCast(*const i32, float_ptr);
22 const int_val = int_ptr.*;
23 assert(int_val == 858993411);
24}
25
26test "implicitly cast indirect pointer to maybe-indirect pointer" {
27 const S = struct {
28 const Self = @This();
29 x: u8,
30 fn constConst(p: *const *const Self) u8 {
31 return p.*.x;
32 }
33 fn maybeConstConst(p: ?*const *const Self) u8 {
34 return p.?.*.x;
35 }
36 fn constConstConst(p: *const *const *const Self) u8 {
37 return p.*.*.x;
38 }
39 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
40 return p.?.*.*.x;
41 }
42 };
43 const s = S{ .x = 42 };
44 const p = &s;
45 const q = &p;
46 const r = &q;
47 assert(42 == S.constConst(q));
48 assert(42 == S.maybeConstConst(q));
49 assert(42 == S.constConstConst(r));
50 assert(42 == S.maybeConstConstConst(r));
51}
52
53test "explicit cast from integer to error type" {
54 testCastIntToErr(error.ItBroke);
55 comptime testCastIntToErr(error.ItBroke);
56}
57fn testCastIntToErr(err: anyerror) void {
58 const x = @errorToInt(err);
59 const y = @intToError(x);
60 assert(error.ItBroke == y);
61}
62
63test "peer resolve arrays of different size to const slice" {
64 assert(mem.eql(u8, boolToStr(true), "true"));
65 assert(mem.eql(u8, boolToStr(false), "false"));
66 comptime assert(mem.eql(u8, boolToStr(true), "true"));
67 comptime assert(mem.eql(u8, boolToStr(false), "false"));
68}
69fn boolToStr(b: bool) []const u8 {
70 return if (b) "true" else "false";
71}
72
73test "peer resolve array and const slice" {
74 testPeerResolveArrayConstSlice(true);
75 comptime testPeerResolveArrayConstSlice(true);
76}
77fn testPeerResolveArrayConstSlice(b: bool) void {
78 const value1 = if (b) "aoeu" else ([]const u8)("zz");
79 const value2 = if (b) ([]const u8)("zz") else "aoeu";
80 assert(mem.eql(u8, value1, "aoeu"));
81 assert(mem.eql(u8, value2, "zz"));
82}
83
84test "implicitly cast from T to anyerror!?T" {
85 castToOptionalTypeError(1);
86 comptime castToOptionalTypeError(1);
87}
88const A = struct {
89 a: i32,
90};
91fn castToOptionalTypeError(z: i32) void {
92 const x = i32(1);
93 const y: anyerror!?i32 = x;
94 assert((try y).? == 1);
95
96 const f = z;
97 const g: anyerror!?i32 = f;
98
99 const a = A{ .a = z };
100 const b: anyerror!?A = a;
101 assert((b catch unreachable).?.a == 1);
102}
103
104test "implicitly cast from int to anyerror!?T" {
105 implicitIntLitToOptional();
106 comptime implicitIntLitToOptional();
107}
108fn implicitIntLitToOptional() void {
109 const f: ?i32 = 1;
110 const g: anyerror!?i32 = 1;
111}
112
113test "return null from fn() anyerror!?&T" {
114 const a = returnNullFromOptionalTypeErrorRef();
115 const b = returnNullLitFromOptionalTypeErrorRef();
116 assert((try a) == null and (try b) == null);
117}
118fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
119 const a: ?*A = null;
120 return a;
121}
122fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
123 return null;
124}
125
126test "peer type resolution: ?T and T" {
127 assert(peerTypeTAndOptionalT(true, false).? == 0);
128 assert(peerTypeTAndOptionalT(false, false).? == 3);
129 comptime {
130 assert(peerTypeTAndOptionalT(true, false).? == 0);
131 assert(peerTypeTAndOptionalT(false, false).? == 3);
132 }
133}
134fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
135 if (c) {
136 return if (b) null else usize(0);
137 }
138
139 return usize(3);
140}
141
142test "peer type resolution: [0]u8 and []const u8" {
143 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
144 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
145 comptime {
146 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
147 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
148 }
149}
150fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
151 if (a) {
152 return []const u8{};
153 }
154
155 return slice[0..1];
156}
157
158test "implicitly cast from [N]T to ?[]const T" {
159 assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
160 comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
161}
162
163fn castToOptionalSlice() ?[]const u8 {
164 return "hi";
165}
166
167test "implicitly cast from [0]T to anyerror![]T" {
168 testCastZeroArrayToErrSliceMut();
169 comptime testCastZeroArrayToErrSliceMut();
170}
171
172fn testCastZeroArrayToErrSliceMut() void {
173 assert((gimmeErrOrSlice() catch unreachable).len == 0);
174}
175
176fn gimmeErrOrSlice() anyerror![]u8 {
177 return []u8{};
178}
179
180test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
181 {
182 var data = "hi";
183 const slice = data[0..];
184 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
185 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
186 }
187 comptime {
188 var data = "hi";
189 const slice = data[0..];
190 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
191 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
192 }
193}
194fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
195 if (a) {
196 return []u8{};
197 }
198
199 return slice[0..1];
200}
201
202test "resolve undefined with integer" {
203 testResolveUndefWithInt(true, 1234);
204 comptime testResolveUndefWithInt(true, 1234);
205}
206fn testResolveUndefWithInt(b: bool, x: i32) void {
207 const value = if (b) x else undefined;
208 if (b) {
209 assert(value == x);
210 }
211}
212
213test "implicit cast from &const [N]T to []const T" {
214 testCastConstArrayRefToConstSlice();
215 comptime testCastConstArrayRefToConstSlice();
216}
217
218fn testCastConstArrayRefToConstSlice() void {
219 const blah = "aoeu";
220 const const_array_ref = &blah;
221 assert(@typeOf(const_array_ref) == *const [4]u8);
222 const slice: []const u8 = const_array_ref;
223 assert(mem.eql(u8, slice, "aoeu"));
224}
225
226test "peer type resolution: error and [N]T" {
227 // TODO: implicit error!T to error!U where T can implicitly cast to U
228 //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
229 //comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
230 assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
231 comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
232}
233
234//fn testPeerErrorAndArray(x: u8) error![]const u8 {
235// return switch (x) {
236// 0x00 => "OK",
237// else => error.BadValue,
238// };
239//}
240fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
241 return switch (x) {
242 0x00 => "OK",
243 0x01 => "OKK",
244 else => error.BadValue,
245 };
246}
247
248test "@floatToInt" {
249 testFloatToInts();
250 comptime testFloatToInts();
251}
252
253fn testFloatToInts() void {
254 const x = i32(1e4);
255 assert(x == 10000);
256 const y = @floatToInt(i32, f32(1e4));
257 assert(y == 10000);
258 expectFloatToInt(f16, 255.1, u8, 255);
259 expectFloatToInt(f16, 127.2, i8, 127);
260 expectFloatToInt(f16, -128.2, i8, -128);
261 expectFloatToInt(f32, 255.1, u8, 255);
262 expectFloatToInt(f32, 127.2, i8, 127);
263 expectFloatToInt(f32, -128.2, i8, -128);
264 expectFloatToInt(comptime_int, 1234, i16, 1234);
265}
266
267fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
268 assert(@floatToInt(I, f) == i);
269}
270
271test "cast u128 to f128 and back" {
272 comptime testCast128();
273 testCast128();
274}
275
276fn testCast128() void {
277 assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
278}
279
280fn cast128Int(x: f128) u128 {
281 return @bitCast(u128, x);
282}
283
284fn cast128Float(x: u128) f128 {
285 return @bitCast(f128, x);
286}
287
288test "const slice widen cast" {
289 const bytes align(4) = []u8{
290 0x12,
291 0x12,
292 0x12,
293 0x12,
294 };
295
296 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
297 assert(u32_value == 0x12121212);
298
299 assert(@bitCast(u32, bytes) == 0x12121212);
300}
301
302test "single-item pointer of array to slice and to unknown length pointer" {
303 testCastPtrOfArrayToSliceAndPtr();
304 comptime testCastPtrOfArrayToSliceAndPtr();
305}
306
307fn testCastPtrOfArrayToSliceAndPtr() void {
308 var array = "aoeu";
309 const x: [*]u8 = &array;
310 x[0] += 1;
311 assert(mem.eql(u8, array[0..], "boeu"));
312 const y: []u8 = &array;
313 y[0] += 1;
314 assert(mem.eql(u8, array[0..], "coeu"));
315}
316
317test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
318 const window_name = [1][*]const u8{c"window name"};
319 const x: [*]const ?[*]const u8 = &window_name;
320 assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
321}
322
323test "@intCast comptime_int" {
324 const result = @intCast(i32, 1234);
325 assert(@typeOf(result) == i32);
326 assert(result == 1234);
327}
328
329test "@floatCast comptime_int and comptime_float" {
330 {
331 const result = @floatCast(f16, 1234);
332 assert(@typeOf(result) == f16);
333 assert(result == 1234.0);
334 }
335 {
336 const result = @floatCast(f16, 1234.0);
337 assert(@typeOf(result) == f16);
338 assert(result == 1234.0);
339 }
340 {
341 const result = @floatCast(f32, 1234);
342 assert(@typeOf(result) == f32);
343 assert(result == 1234.0);
344 }
345 {
346 const result = @floatCast(f32, 1234.0);
347 assert(@typeOf(result) == f32);
348 assert(result == 1234.0);
349 }
350}
351
352test "comptime_int @intToFloat" {
353 {
354 const result = @intToFloat(f16, 1234);
355 assert(@typeOf(result) == f16);
356 assert(result == 1234.0);
357 }
358 {
359 const result = @intToFloat(f32, 1234);
360 assert(@typeOf(result) == f32);
361 assert(result == 1234.0);
362 }
363}
364
365test "@bytesToSlice keeps pointer alignment" {
366 var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
367 const numbers = @bytesToSlice(u32, bytes[0..]);
368 comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
369}
370
371test "@intCast i32 to u7" {
372 var x: u128 = maxInt(u128);
373 var y: i32 = 120;
374 var z = x >> @intCast(u7, y);
375 assert(z == 0xff);
376}
377
378test "implicit cast undefined to optional" {
379 assert(MakeType(void).getNull() == null);
380 assert(MakeType(void).getNonNull() != null);
381}
382
383fn MakeType(comptime T: type) type {
384 return struct {
385 fn getNull() ?T {
386 return null;
387 }
388
389 fn getNonNull() ?T {
390 return T(undefined);
391 }
392 };
393}
394
395test "implicit cast from *[N]T to ?[*]T" {
396 var x: ?[*]u16 = null;
397 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
398
399 x = &y;
400 assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
401 x.?[0] = 8;
402 y[3] = 6;
403 assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
404}
405
406test "implicit cast from *T to ?*c_void" {
407 var a: u8 = 1;
408 incrementVoidPtrValue(&a);
409 std.debug.assert(a == 2);
410}
411
412fn incrementVoidPtrValue(value: ?*c_void) void {
413 @ptrCast(*u8, value.?).* += 1;
414}
415
416test "implicit cast from [*]T to ?*c_void" {
417 var a = []u8{ 3, 2, 1 };
418 incrementVoidPtrArray(a[0..].ptr, 3);
419 assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
420}
421
422fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
423 var n: usize = 0;
424 while (n < len) : (n += 1) {
425 @ptrCast([*]u8, array.?)[n] += 1;
426 }
427}
428
429test "*usize to *void" {
430 var i = usize(0);
431 var v = @ptrCast(*void, &i);
432 v.* = {};
433}
434
435test "compile time int to ptr of function" {
436 foobar(FUNCTION_CONSTANT);
437}
438
439pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
440pub const PFN_void = extern fn (*c_void) void;
441
442fn foobar(func: PFN_void) void {
443 std.debug.assert(@ptrToInt(func) == maxInt(usize));
444}
445
446test "implicit ptr to *c_void" {
447 var a: u32 = 1;
448 var ptr: *c_void = &a;
449 var b: *u32 = @ptrCast(*u32, ptr);
450 assert(b.* == 1);
451 var ptr2: ?*c_void = &a;
452 var c: *u32 = @ptrCast(*u32, ptr2.?);
453 assert(c.* == 1);
454}
455
456test "@intCast to comptime_int" {
457 assert(@intCast(comptime_int, 0) == 0);
458}
459
460test "implicit cast comptime numbers to any type when the value fits" {
461 const a: u64 = 255;
462 var b: u8 = a;
463 assert(b == 255);
464}
465
466test "@intToEnum passed a comptime_int to an enum with one item" {
467 const E = enum {
468 A,
469 };
470 const x = @intToEnum(E, 0);
471 assert(x == E.A);
472}
test/cases/const_slice_child.zig deleted-45
......@@ -1,45 +0,0 @@
1const debug = @import("std").debug;
2const assert = debug.assert;
3
4var argv: [*]const [*]const u8 = undefined;
5
6test "const slice child" {
7 const strs = ([][*]const u8){
8 c"one",
9 c"two",
10 c"three",
11 };
12 // TODO this should implicitly cast
13 argv = @ptrCast([*]const [*]const u8, &strs);
14 bar(strs.len);
15}
16
17fn foo(args: [][]const u8) void {
18 assert(args.len == 3);
19 assert(streql(args[0], "one"));
20 assert(streql(args[1], "two"));
21 assert(streql(args[2], "three"));
22}
23
24fn bar(argc: usize) void {
25 const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable;
26 for (args) |_, i| {
27 const ptr = argv[i];
28 args[i] = ptr[0..strlen(ptr)];
29 }
30 foo(args);
31}
32
33fn strlen(ptr: [*]const u8) usize {
34 var count: usize = 0;
35 while (ptr[count] != 0) : (count += 1) {}
36 return count;
37}
38
39fn streql(a: []const u8, b: []const u8) bool {
40 if (a.len != b.len) return false;
41 for (a) |item, index| {
42 if (b[index] != item) return false;
43 }
44 return true;
45}
test/cases/coroutine_await_struct.zig deleted-47
......@@ -1,47 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: promise = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 var da = std.heap.DirectAllocator.init();
14 defer da.deinit();
15
16 await_seq('a');
17 const p = async<&da.allocator> await_amain() catch unreachable;
18 await_seq('f');
19 resume await_a_promise;
20 await_seq('i');
21 assert(await_final_result.x == 1234);
22 assert(std.mem.eql(u8, await_points, "abcdefghi"));
23}
24async fn await_amain() void {
25 await_seq('b');
26 const p = async await_another() catch unreachable;
27 await_seq('e');
28 await_final_result = await p;
29 await_seq('h');
30}
31async fn await_another() Foo {
32 await_seq('c');
33 suspend {
34 await_seq('d');
35 await_a_promise = @handle();
36 }
37 await_seq('g');
38 return Foo{ .x = 1234 };
39}
40
41var await_points = []u8{0} ** "abcdefghi".len;
42var await_seq_index: usize = 0;
43
44fn await_seq(c: u8) void {
45 await_points[await_seq_index] = c;
46 await_seq_index += 1;
47}
test/cases/coroutines.zig deleted-258
......@@ -1,258 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5var x: i32 = 1;
6
7test "create a coroutine and cancel it" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = try async<&da.allocator> simpleAsyncFn();
12 comptime assert(@typeOf(p) == promise->void);
13 cancel p;
14 assert(x == 2);
15}
16async fn simpleAsyncFn() void {
17 x += 1;
18 suspend;
19 x += 1;
20}
21
22test "coroutine suspend, resume, cancel" {
23 var da = std.heap.DirectAllocator.init();
24 defer da.deinit();
25
26 seq('a');
27 const p = try async<&da.allocator> testAsyncSeq();
28 seq('c');
29 resume p;
30 seq('f');
31 cancel p;
32 seq('g');
33
34 assert(std.mem.eql(u8, points, "abcdefg"));
35}
36async fn testAsyncSeq() void {
37 defer seq('e');
38
39 seq('b');
40 suspend;
41 seq('d');
42}
43var points = []u8{0} ** "abcdefg".len;
44var index: usize = 0;
45
46fn seq(c: u8) void {
47 points[index] = c;
48 index += 1;
49}
50
51test "coroutine suspend with block" {
52 var da = std.heap.DirectAllocator.init();
53 defer da.deinit();
54
55 const p = try async<&da.allocator> testSuspendBlock();
56 std.debug.assert(!result);
57 resume a_promise;
58 std.debug.assert(result);
59 cancel p;
60}
61
62var a_promise: promise = undefined;
63var result = false;
64async fn testSuspendBlock() void {
65 suspend {
66 comptime assert(@typeOf(@handle()) == promise->void);
67 a_promise = @handle();
68 }
69
70 //Test to make sure that @handle() works as advertised (issue #1296)
71 //var our_handle: promise = @handle();
72 assert( a_promise == @handle() );
73
74 result = true;
75}
76
77var await_a_promise: promise = undefined;
78var await_final_result: i32 = 0;
79
80test "coroutine await" {
81 var da = std.heap.DirectAllocator.init();
82 defer da.deinit();
83
84 await_seq('a');
85 const p = async<&da.allocator> await_amain() catch unreachable;
86 await_seq('f');
87 resume await_a_promise;
88 await_seq('i');
89 assert(await_final_result == 1234);
90 assert(std.mem.eql(u8, await_points, "abcdefghi"));
91}
92async fn await_amain() void {
93 await_seq('b');
94 const p = async await_another() catch unreachable;
95 await_seq('e');
96 await_final_result = await p;
97 await_seq('h');
98}
99async fn await_another() i32 {
100 await_seq('c');
101 suspend {
102 await_seq('d');
103 await_a_promise = @handle();
104 }
105 await_seq('g');
106 return 1234;
107}
108
109var await_points = []u8{0} ** "abcdefghi".len;
110var await_seq_index: usize = 0;
111
112fn await_seq(c: u8) void {
113 await_points[await_seq_index] = c;
114 await_seq_index += 1;
115}
116
117var early_final_result: i32 = 0;
118
119test "coroutine await early return" {
120 var da = std.heap.DirectAllocator.init();
121 defer da.deinit();
122
123 early_seq('a');
124 const p = async<&da.allocator> early_amain() catch @panic("out of memory");
125 early_seq('f');
126 assert(early_final_result == 1234);
127 assert(std.mem.eql(u8, early_points, "abcdef"));
128}
129async fn early_amain() void {
130 early_seq('b');
131 const p = async early_another() catch @panic("out of memory");
132 early_seq('d');
133 early_final_result = await p;
134 early_seq('e');
135}
136async fn early_another() i32 {
137 early_seq('c');
138 return 1234;
139}
140
141var early_points = []u8{0} ** "abcdef".len;
142var early_seq_index: usize = 0;
143
144fn early_seq(c: u8) void {
145 early_points[early_seq_index] = c;
146 early_seq_index += 1;
147}
148
149test "coro allocation failure" {
150 var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);
151 if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) {
152 @panic("expected allocation failure");
153 } else |err| switch (err) {
154 error.OutOfMemory => {},
155 }
156}
157async fn asyncFuncThatNeverGetsRun() void {
158 @panic("coro frame allocation should fail");
159}
160
161test "async function with dot syntax" {
162 const S = struct {
163 var y: i32 = 1;
164 async fn foo() void {
165 y += 1;
166 suspend;
167 }
168 };
169 var da = std.heap.DirectAllocator.init();
170 defer da.deinit();
171 const p = try async<&da.allocator> S.foo();
172 cancel p;
173 assert(S.y == 2);
174}
175
176test "async fn pointer in a struct field" {
177 var data: i32 = 1;
178 const Foo = struct {
179 bar: async<*std.mem.Allocator> fn (*i32) void,
180 };
181 var foo = Foo{ .bar = simpleAsyncFn2 };
182 var da = std.heap.DirectAllocator.init();
183 defer da.deinit();
184 const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
185 assert(data == 2);
186 cancel p;
187 assert(data == 4);
188}
189async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
190 defer y.* += 2;
191 y.* += 1;
192 suspend;
193}
194
195test "async fn with inferred error set" {
196 var da = std.heap.DirectAllocator.init();
197 defer da.deinit();
198 const p = (async<&da.allocator> failing()) catch unreachable;
199 resume p;
200 cancel p;
201}
202async fn failing() !void {
203 suspend;
204 return error.Fail;
205}
206
207test "error return trace across suspend points - early return" {
208 const p = nonFailing();
209 resume p;
210 var da = std.heap.DirectAllocator.init();
211 defer da.deinit();
212 const p2 = try async<&da.allocator> printTrace(p);
213 cancel p2;
214}
215
216test "error return trace across suspend points - async return" {
217 const p = nonFailing();
218 const p2 = try async<std.debug.global_allocator> printTrace(p);
219 resume p;
220 cancel p2;
221}
222
223// TODO https://github.com/ziglang/zig/issues/760
224fn nonFailing() promise->(anyerror!void) {
225 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
226}
227async fn suspendThenFail() anyerror!void {
228 suspend;
229 return error.Fail;
230}
231async fn printTrace(p: promise->(anyerror!void)) void {
232 (await p) catch |e| {
233 std.debug.assert(e == error.Fail);
234 if (@errorReturnTrace()) |trace| {
235 assert(trace.index == 1);
236 } else switch (builtin.mode) {
237 builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
238 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
239 }
240 };
241}
242
243test "break from suspend" {
244 var buf: [500]u8 = undefined;
245 var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
246 var my_result: i32 = 1;
247 const p = try async<a> testBreakFromSuspend(&my_result);
248 cancel p;
249 std.debug.assert(my_result == 2);
250}
251async fn testBreakFromSuspend(my_result: *i32) void {
252 suspend {
253 resume @handle();
254 }
255 my_result.* += 1;
256 suspend;
257 my_result.* += 1;
258}
test/cases/defer.zig deleted-78
......@@ -1,78 +0,0 @@
1const assert = @import("std").debug.assert;
2
3var result: [3]u8 = undefined;
4var index: usize = undefined;
5
6fn runSomeErrorDefers(x: bool) !bool {
7 index = 0;
8 defer {
9 result[index] = 'a';
10 index += 1;
11 }
12 errdefer {
13 result[index] = 'b';
14 index += 1;
15 }
16 defer {
17 result[index] = 'c';
18 index += 1;
19 }
20 return if (x) x else error.FalseNotAllowed;
21}
22
23test "mixing normal and error defers" {
24 assert(runSomeErrorDefers(true) catch unreachable);
25 assert(result[0] == 'c');
26 assert(result[1] == 'a');
27
28 const ok = runSomeErrorDefers(false) catch |err| x: {
29 assert(err == error.FalseNotAllowed);
30 break :x true;
31 };
32 assert(ok);
33 assert(result[0] == 'c');
34 assert(result[1] == 'b');
35 assert(result[2] == 'a');
36}
37
38test "break and continue inside loop inside defer expression" {
39 testBreakContInDefer(10);
40 comptime testBreakContInDefer(10);
41}
42
43fn testBreakContInDefer(x: usize) void {
44 defer {
45 var i: usize = 0;
46 while (i < x) : (i += 1) {
47 if (i < 5) continue;
48 if (i == 5) break;
49 }
50 assert(i == 5);
51 }
52}
53
54test "defer and labeled break" {
55 var i = usize(0);
56
57 blk: {
58 defer i += 1;
59 break :blk;
60 }
61
62 assert(i == 1);
63}
64
65test "errdefer does not apply to fn inside fn" {
66 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad);
67}
68
69fn testNestedFnErrDefer() anyerror!void {
70 var a: i32 = 0;
71 errdefer a += 1;
72 const S = struct {
73 fn baz() anyerror {
74 return error.Bad;
75 }
76 };
77 return S.baz();
78}
test/cases/enum.zig deleted-894
......@@ -1,894 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4test "enum type" {
5 const foo1 = Foo{ .One = 13 };
6 const foo2 = Foo{
7 .Two = Point{
8 .x = 1234,
9 .y = 5678,
10 },
11 };
12 const bar = Bar.B;
13
14 assert(bar == Bar.B);
15 assert(@memberCount(Foo) == 3);
16 assert(@memberCount(Bar) == 4);
17 assert(@sizeOf(Foo) == @sizeOf(FooNoVoid));
18 assert(@sizeOf(Bar) == 1);
19}
20
21test "enum as return value" {
22 switch (returnAnInt(13)) {
23 Foo.One => |value| assert(value == 13),
24 else => unreachable,
25 }
26}
27
28const Point = struct {
29 x: u64,
30 y: u64,
31};
32const Foo = union(enum) {
33 One: i32,
34 Two: Point,
35 Three: void,
36};
37const FooNoVoid = union(enum) {
38 One: i32,
39 Two: Point,
40};
41const Bar = enum {
42 A,
43 B,
44 C,
45 D,
46};
47
48fn returnAnInt(x: i32) Foo {
49 return Foo{ .One = x };
50}
51
52test "constant enum with payload" {
53 var empty = AnEnumWithPayload{ .Empty = {} };
54 var full = AnEnumWithPayload{ .Full = 13 };
55 shouldBeEmpty(empty);
56 shouldBeNotEmpty(full);
57}
58
59fn shouldBeEmpty(x: AnEnumWithPayload) void {
60 switch (x) {
61 AnEnumWithPayload.Empty => {},
62 else => unreachable,
63 }
64}
65
66fn shouldBeNotEmpty(x: AnEnumWithPayload) void {
67 switch (x) {
68 AnEnumWithPayload.Empty => unreachable,
69 else => {},
70 }
71}
72
73const AnEnumWithPayload = union(enum) {
74 Empty: void,
75 Full: i32,
76};
77
78const Number = enum {
79 Zero,
80 One,
81 Two,
82 Three,
83 Four,
84};
85
86test "enum to int" {
87 shouldEqual(Number.Zero, 0);
88 shouldEqual(Number.One, 1);
89 shouldEqual(Number.Two, 2);
90 shouldEqual(Number.Three, 3);
91 shouldEqual(Number.Four, 4);
92}
93
94fn shouldEqual(n: Number, expected: u3) void {
95 assert(@enumToInt(n) == expected);
96}
97
98test "int to enum" {
99 testIntToEnumEval(3);
100}
101fn testIntToEnumEval(x: i32) void {
102 assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103}
104const IntToEnumNumber = enum {
105 Zero,
106 One,
107 Two,
108 Three,
109 Four,
110};
111
112test "@tagName" {
113 assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
115}
116
117fn testEnumTagNameBare(n: BareNumber) []const u8 {
118 return @tagName(n);
119}
120
121const BareNumber = enum {
122 One,
123 Two,
124 Three,
125};
126
127test "enum alignment" {
128 comptime {
129 assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
130 assert(@alignOf(AlignTestEnum) >= @alignOf(u64));
131 }
132}
133
134const AlignTestEnum = union(enum) {
135 A: [9]u8,
136 B: u64,
137};
138
139const ValueCount1 = enum {
140 I0,
141};
142const ValueCount2 = enum {
143 I0,
144 I1,
145};
146const ValueCount256 = enum {
147 I0,
148 I1,
149 I2,
150 I3,
151 I4,
152 I5,
153 I6,
154 I7,
155 I8,
156 I9,
157 I10,
158 I11,
159 I12,
160 I13,
161 I14,
162 I15,
163 I16,
164 I17,
165 I18,
166 I19,
167 I20,
168 I21,
169 I22,
170 I23,
171 I24,
172 I25,
173 I26,
174 I27,
175 I28,
176 I29,
177 I30,
178 I31,
179 I32,
180 I33,
181 I34,
182 I35,
183 I36,
184 I37,
185 I38,
186 I39,
187 I40,
188 I41,
189 I42,
190 I43,
191 I44,
192 I45,
193 I46,
194 I47,
195 I48,
196 I49,
197 I50,
198 I51,
199 I52,
200 I53,
201 I54,
202 I55,
203 I56,
204 I57,
205 I58,
206 I59,
207 I60,
208 I61,
209 I62,
210 I63,
211 I64,
212 I65,
213 I66,
214 I67,
215 I68,
216 I69,
217 I70,
218 I71,
219 I72,
220 I73,
221 I74,
222 I75,
223 I76,
224 I77,
225 I78,
226 I79,
227 I80,
228 I81,
229 I82,
230 I83,
231 I84,
232 I85,
233 I86,
234 I87,
235 I88,
236 I89,
237 I90,
238 I91,
239 I92,
240 I93,
241 I94,
242 I95,
243 I96,
244 I97,
245 I98,
246 I99,
247 I100,
248 I101,
249 I102,
250 I103,
251 I104,
252 I105,
253 I106,
254 I107,
255 I108,
256 I109,
257 I110,
258 I111,
259 I112,
260 I113,
261 I114,
262 I115,
263 I116,
264 I117,
265 I118,
266 I119,
267 I120,
268 I121,
269 I122,
270 I123,
271 I124,
272 I125,
273 I126,
274 I127,
275 I128,
276 I129,
277 I130,
278 I131,
279 I132,
280 I133,
281 I134,
282 I135,
283 I136,
284 I137,
285 I138,
286 I139,
287 I140,
288 I141,
289 I142,
290 I143,
291 I144,
292 I145,
293 I146,
294 I147,
295 I148,
296 I149,
297 I150,
298 I151,
299 I152,
300 I153,
301 I154,
302 I155,
303 I156,
304 I157,
305 I158,
306 I159,
307 I160,
308 I161,
309 I162,
310 I163,
311 I164,
312 I165,
313 I166,
314 I167,
315 I168,
316 I169,
317 I170,
318 I171,
319 I172,
320 I173,
321 I174,
322 I175,
323 I176,
324 I177,
325 I178,
326 I179,
327 I180,
328 I181,
329 I182,
330 I183,
331 I184,
332 I185,
333 I186,
334 I187,
335 I188,
336 I189,
337 I190,
338 I191,
339 I192,
340 I193,
341 I194,
342 I195,
343 I196,
344 I197,
345 I198,
346 I199,
347 I200,
348 I201,
349 I202,
350 I203,
351 I204,
352 I205,
353 I206,
354 I207,
355 I208,
356 I209,
357 I210,
358 I211,
359 I212,
360 I213,
361 I214,
362 I215,
363 I216,
364 I217,
365 I218,
366 I219,
367 I220,
368 I221,
369 I222,
370 I223,
371 I224,
372 I225,
373 I226,
374 I227,
375 I228,
376 I229,
377 I230,
378 I231,
379 I232,
380 I233,
381 I234,
382 I235,
383 I236,
384 I237,
385 I238,
386 I239,
387 I240,
388 I241,
389 I242,
390 I243,
391 I244,
392 I245,
393 I246,
394 I247,
395 I248,
396 I249,
397 I250,
398 I251,
399 I252,
400 I253,
401 I254,
402 I255,
403};
404const ValueCount257 = enum {
405 I0,
406 I1,
407 I2,
408 I3,
409 I4,
410 I5,
411 I6,
412 I7,
413 I8,
414 I9,
415 I10,
416 I11,
417 I12,
418 I13,
419 I14,
420 I15,
421 I16,
422 I17,
423 I18,
424 I19,
425 I20,
426 I21,
427 I22,
428 I23,
429 I24,
430 I25,
431 I26,
432 I27,
433 I28,
434 I29,
435 I30,
436 I31,
437 I32,
438 I33,
439 I34,
440 I35,
441 I36,
442 I37,
443 I38,
444 I39,
445 I40,
446 I41,
447 I42,
448 I43,
449 I44,
450 I45,
451 I46,
452 I47,
453 I48,
454 I49,
455 I50,
456 I51,
457 I52,
458 I53,
459 I54,
460 I55,
461 I56,
462 I57,
463 I58,
464 I59,
465 I60,
466 I61,
467 I62,
468 I63,
469 I64,
470 I65,
471 I66,
472 I67,
473 I68,
474 I69,
475 I70,
476 I71,
477 I72,
478 I73,
479 I74,
480 I75,
481 I76,
482 I77,
483 I78,
484 I79,
485 I80,
486 I81,
487 I82,
488 I83,
489 I84,
490 I85,
491 I86,
492 I87,
493 I88,
494 I89,
495 I90,
496 I91,
497 I92,
498 I93,
499 I94,
500 I95,
501 I96,
502 I97,
503 I98,
504 I99,
505 I100,
506 I101,
507 I102,
508 I103,
509 I104,
510 I105,
511 I106,
512 I107,
513 I108,
514 I109,
515 I110,
516 I111,
517 I112,
518 I113,
519 I114,
520 I115,
521 I116,
522 I117,
523 I118,
524 I119,
525 I120,
526 I121,
527 I122,
528 I123,
529 I124,
530 I125,
531 I126,
532 I127,
533 I128,
534 I129,
535 I130,
536 I131,
537 I132,
538 I133,
539 I134,
540 I135,
541 I136,
542 I137,
543 I138,
544 I139,
545 I140,
546 I141,
547 I142,
548 I143,
549 I144,
550 I145,
551 I146,
552 I147,
553 I148,
554 I149,
555 I150,
556 I151,
557 I152,
558 I153,
559 I154,
560 I155,
561 I156,
562 I157,
563 I158,
564 I159,
565 I160,
566 I161,
567 I162,
568 I163,
569 I164,
570 I165,
571 I166,
572 I167,
573 I168,
574 I169,
575 I170,
576 I171,
577 I172,
578 I173,
579 I174,
580 I175,
581 I176,
582 I177,
583 I178,
584 I179,
585 I180,
586 I181,
587 I182,
588 I183,
589 I184,
590 I185,
591 I186,
592 I187,
593 I188,
594 I189,
595 I190,
596 I191,
597 I192,
598 I193,
599 I194,
600 I195,
601 I196,
602 I197,
603 I198,
604 I199,
605 I200,
606 I201,
607 I202,
608 I203,
609 I204,
610 I205,
611 I206,
612 I207,
613 I208,
614 I209,
615 I210,
616 I211,
617 I212,
618 I213,
619 I214,
620 I215,
621 I216,
622 I217,
623 I218,
624 I219,
625 I220,
626 I221,
627 I222,
628 I223,
629 I224,
630 I225,
631 I226,
632 I227,
633 I228,
634 I229,
635 I230,
636 I231,
637 I232,
638 I233,
639 I234,
640 I235,
641 I236,
642 I237,
643 I238,
644 I239,
645 I240,
646 I241,
647 I242,
648 I243,
649 I244,
650 I245,
651 I246,
652 I247,
653 I248,
654 I249,
655 I250,
656 I251,
657 I252,
658 I253,
659 I254,
660 I255,
661 I256,
662};
663
664test "enum sizes" {
665 comptime {
666 assert(@sizeOf(ValueCount1) == 0);
667 assert(@sizeOf(ValueCount2) == 1);
668 assert(@sizeOf(ValueCount256) == 1);
669 assert(@sizeOf(ValueCount257) == 2);
670 }
671}
672
673const Small2 = enum(u2) {
674 One,
675 Two,
676};
677const Small = enum(u2) {
678 One,
679 Two,
680 Three,
681 Four,
682};
683
684test "set enum tag type" {
685 {
686 var x = Small.One;
687 x = Small.Two;
688 comptime assert(@TagType(Small) == u2);
689 }
690 {
691 var x = Small2.One;
692 x = Small2.Two;
693 comptime assert(@TagType(Small2) == u2);
694 }
695}
696
697const A = enum(u3) {
698 One,
699 Two,
700 Three,
701 Four,
702 One2,
703 Two2,
704 Three2,
705 Four2,
706};
707
708const B = enum(u3) {
709 One3,
710 Two3,
711 Three3,
712 Four3,
713 One23,
714 Two23,
715 Three23,
716 Four23,
717};
718
719const C = enum(u2) {
720 One4,
721 Two4,
722 Three4,
723 Four4,
724};
725
726const BitFieldOfEnums = packed struct {
727 a: A,
728 b: B,
729 c: C,
730};
731
732const bit_field_1 = BitFieldOfEnums{
733 .a = A.Two,
734 .b = B.Three3,
735 .c = C.Four4,
736};
737
738test "bit field access with enum fields" {
739 var data = bit_field_1;
740 assert(getA(&data) == A.Two);
741 assert(getB(&data) == B.Three3);
742 assert(getC(&data) == C.Four4);
743 comptime assert(@sizeOf(BitFieldOfEnums) == 1);
744
745 data.b = B.Four3;
746 assert(data.b == B.Four3);
747
748 data.a = A.Three;
749 assert(data.a == A.Three);
750 assert(data.b == B.Four3);
751}
752
753fn getA(data: *const BitFieldOfEnums) A {
754 return data.a;
755}
756
757fn getB(data: *const BitFieldOfEnums) B {
758 return data.b;
759}
760
761fn getC(data: *const BitFieldOfEnums) C {
762 return data.c;
763}
764
765test "casting enum to its tag type" {
766 testCastEnumToTagType(Small2.Two);
767 comptime testCastEnumToTagType(Small2.Two);
768}
769
770fn testCastEnumToTagType(value: Small2) void {
771 assert(@enumToInt(value) == 1);
772}
773
774const MultipleChoice = enum(u32) {
775 A = 20,
776 B = 40,
777 C = 60,
778 D = 1000,
779};
780
781test "enum with specified tag values" {
782 testEnumWithSpecifiedTagValues(MultipleChoice.C);
783 comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
784}
785
786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 assert(@enumToInt(x) == 60);
788 assert(1234 == switch (x) {
789 MultipleChoice.A => 1,
790 MultipleChoice.B => 2,
791 MultipleChoice.C => u32(1234),
792 MultipleChoice.D => 4,
793 });
794}
795
796const MultipleChoice2 = enum(u32) {
797 Unspecified1,
798 A = 20,
799 Unspecified2,
800 B = 40,
801 Unspecified3,
802 C = 60,
803 Unspecified4,
804 D = 1000,
805 Unspecified5,
806};
807
808test "enum with specified and unspecified tag values" {
809 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
810 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
811}
812
813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 assert(@enumToInt(x) == 1000);
815 assert(1234 == switch (x) {
816 MultipleChoice2.A => 1,
817 MultipleChoice2.B => 2,
818 MultipleChoice2.C => 3,
819 MultipleChoice2.D => u32(1234),
820 MultipleChoice2.Unspecified1 => 5,
821 MultipleChoice2.Unspecified2 => 6,
822 MultipleChoice2.Unspecified3 => 7,
823 MultipleChoice2.Unspecified4 => 8,
824 MultipleChoice2.Unspecified5 => 9,
825 });
826}
827
828test "cast integer literal to enum" {
829 assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831}
832
833const EnumWithOneMember = enum {
834 Eof,
835};
836
837fn doALoopThing(id: EnumWithOneMember) void {
838 while (true) {
839 if (id == EnumWithOneMember.Eof) {
840 break;
841 }
842 @compileError("above if condition should be comptime");
843 }
844}
845
846test "comparison operator on enum with one member is comptime known" {
847 doALoopThing(EnumWithOneMember.Eof);
848}
849
850const State = enum {
851 Start,
852};
853test "switch on enum with one member is comptime known" {
854 var state = State.Start;
855 switch (state) {
856 State.Start => return,
857 }
858 @compileError("analysis should not reach here");
859}
860
861const EnumWithTagValues = enum(u4) {
862 A = 1 << 0,
863 B = 1 << 1,
864 C = 1 << 2,
865 D = 1 << 3,
866};
867test "enum with tag values don't require parens" {
868 assert(@enumToInt(EnumWithTagValues.C) == 0b0100);
869}
870
871test "enum with 1 field but explicit tag type should still have the tag type" {
872 const Enum = enum(u8) {
873 B = 2,
874 };
875 comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8));
876}
877
878test "empty extern enum with members" {
879 const E = extern enum {
880 A,
881 B,
882 C,
883 };
884 assert(@sizeOf(E) == @sizeOf(c_int));
885}
886
887test "aoeu" {
888 const LocalFoo = enum {
889 A = 1,
890 B = 0,
891 };
892 var b = LocalFoo.B;
893 assert(mem.eql(u8, @tagName(b), "B"));
894}
test/cases/enum_with_members.zig deleted-27
......@@ -1,27 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const fmt = @import("std").fmt;
4
5const ET = union(enum) {
6 SINT: i32,
7 UINT: u32,
8
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
13 };
14 }
15};
16
17test "enum with members" {
18 const a = ET{ .SINT = -42 };
19 const b = ET{ .UINT = 42 };
20 var buf: [20]u8 = undefined;
21
22 assert((a.print(buf[0..]) catch unreachable) == 3);
23 assert(mem.eql(u8, buf[0..3], "-42"));
24
25 assert((b.print(buf[0..]) catch unreachable) == 2);
26 assert(mem.eql(u8, buf[0..2], "42"));
27}
test/cases/error.zig deleted-245
......@@ -1,245 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const builtin = @import("builtin");
5
6pub fn foo() anyerror!i32 {
7 const x = try bar();
8 return x + 1;
9}
10
11pub fn bar() anyerror!i32 {
12 return 13;
13}
14
15pub fn baz() anyerror!i32 {
16 const y = foo() catch 1234;
17 return y + 1;
18}
19
20test "error wrapping" {
21 assert((baz() catch unreachable) == 15);
22}
23
24fn gimmeItBroke() []const u8 {
25 return @errorName(error.ItBroke);
26}
27
28test "@errorName" {
29 assert(mem.eql(u8, @errorName(error.AnError), "AnError"));
30 assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
31}
32
33test "error values" {
34 const a = @errorToInt(error.err1);
35 const b = @errorToInt(error.err2);
36 assert(a != b);
37}
38
39test "redefinition of error values allowed" {
40 shouldBeNotEqual(error.AnError, error.SecondError);
41}
42fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
43 if (a == b) unreachable;
44}
45
46test "error binary operator" {
47 const a = errBinaryOperatorG(true) catch 3;
48 const b = errBinaryOperatorG(false) catch 3;
49 assert(a == 3);
50 assert(b == 10);
51}
52fn errBinaryOperatorG(x: bool) anyerror!isize {
53 return if (x) error.ItBroke else isize(10);
54}
55
56test "unwrap simple value from error" {
57 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
58 assert(i == 13);
59}
60fn unwrapSimpleValueFromErrorDo() anyerror!isize {
61 return 13;
62}
63
64test "error return in assignment" {
65 doErrReturnInAssignment() catch unreachable;
66}
67
68fn doErrReturnInAssignment() anyerror!void {
69 var x: i32 = undefined;
70 x = try makeANonErr();
71}
72
73fn makeANonErr() anyerror!i32 {
74 return 1;
75}
76
77test "error union type " {
78 testErrorUnionType();
79 comptime testErrorUnionType();
80}
81
82fn testErrorUnionType() void {
83 const x: anyerror!i32 = 1234;
84 if (x) |value| assert(value == 1234) else |_| unreachable;
85 assert(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
86 assert(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
87 assert(@typeOf(x).ErrorSet == anyerror);
88}
89
90test "error set type " {
91 testErrorSetType();
92 comptime testErrorSetType();
93}
94
95const MyErrSet = error{
96 OutOfMemory,
97 FileNotFound,
98};
99
100fn testErrorSetType() void {
101 assert(@memberCount(MyErrSet) == 2);
102
103 const a: MyErrSet!i32 = 5678;
104 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
105
106 if (a) |value| assert(value == 5678) else |err| switch (err) {
107 error.OutOfMemory => unreachable,
108 error.FileNotFound => unreachable,
109 }
110}
111
112test "explicit error set cast" {
113 testExplicitErrorSetCast(Set1.A);
114 comptime testExplicitErrorSetCast(Set1.A);
115}
116
117const Set1 = error{
118 A,
119 B,
120};
121const Set2 = error{
122 A,
123 C,
124};
125
126fn testExplicitErrorSetCast(set1: Set1) void {
127 var x = @errSetCast(Set2, set1);
128 var y = @errSetCast(Set1, x);
129 assert(y == error.A);
130}
131
132test "comptime test error for empty error set" {
133 testComptimeTestErrorEmptySet(1234);
134 comptime testComptimeTestErrorEmptySet(1234);
135}
136
137const EmptyErrorSet = error{};
138
139fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
140 if (x) |v| assert(v == 1234) else |err| @compileError("bad");
141}
142
143test "syntax: optional operator in front of error union operator" {
144 comptime {
145 assert(?(anyerror!i32) == ?(anyerror!i32));
146 }
147}
148
149test "comptime err to int of error set with only 1 possible value" {
150 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
151 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152}
153fn testErrToIntWithOnePossibleValue(
154 x: error{A},
155 comptime value: u32,
156) void {
157 if (@errorToInt(x) != value) {
158 @compileError("bad");
159 }
160}
161
162test "error union peer type resolution" {
163 testErrorUnionPeerTypeResolution(1);
164 comptime testErrorUnionPeerTypeResolution(1);
165}
166
167fn testErrorUnionPeerTypeResolution(x: i32) void {
168 const y = switch (x) {
169 1 => bar_1(),
170 2 => baz_1(),
171 else => quux_1(),
172 };
173}
174
175fn bar_1() anyerror {
176 return error.A;
177}
178
179fn baz_1() !i32 {
180 return error.B;
181}
182
183fn quux_1() !i32 {
184 return error.C;
185}
186
187test "error: fn returning empty error set can be passed as fn returning any error" {
188 entry();
189 comptime entry();
190}
191
192fn entry() void {
193 foo2(bar2);
194}
195
196fn foo2(f: fn () anyerror!void) void {
197 const x = f();
198}
199
200fn bar2() (error{}!void) {}
201
202test "error: Zero sized error set returned with value payload crash" {
203 _ = foo3(0);
204 _ = comptime foo3(0);
205}
206
207const Error = error{};
208fn foo3(b: usize) Error!usize {
209 return b;
210}
211
212test "error: Infer error set from literals" {
213 _ = nullLiteral("n") catch |err| handleErrors(err);
214 _ = floatLiteral("n") catch |err| handleErrors(err);
215 _ = intLiteral("n") catch |err| handleErrors(err);
216 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
217 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
218 _ = comptime intLiteral("n") catch |err| handleErrors(err);
219}
220
221fn handleErrors(err: var) noreturn {
222 switch (err) {
223 error.T => {},
224 }
225
226 unreachable;
227}
228
229fn nullLiteral(str: []const u8) !?i64 {
230 if (str[0] == 'n') return null;
231
232 return error.T;
233}
234
235fn floatLiteral(str: []const u8) !?f64 {
236 if (str[0] == 'n') return 1.0;
237
238 return error.T;
239}
240
241fn intLiteral(str: []const u8) !?i64 {
242 if (str[0] == 'n') return 1;
243
244 return error.T;
245}
test/cases/eval.zig deleted-782
......@@ -1,782 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4
5test "compile time recursion" {
6 assert(some_data.len == 21);
7}
8var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
9fn fibonacci(x: i32) i32 {
10 if (x <= 1) return 1;
11 return fibonacci(x - 1) + fibonacci(x - 2);
12}
13
14fn unwrapAndAddOne(blah: ?i32) i32 {
15 return blah.? + 1;
16}
17const should_be_1235 = unwrapAndAddOne(1234);
18test "static add one" {
19 assert(should_be_1235 == 1235);
20}
21
22test "inlined loop" {
23 comptime var i = 0;
24 comptime var sum = 0;
25 inline while (i <= 5) : (i += 1)
26 sum += i;
27 assert(sum == 15);
28}
29
30fn gimme1or2(comptime a: bool) i32 {
31 const x: i32 = 1;
32 const y: i32 = 2;
33 comptime var z: i32 = if (a) x else y;
34 return z;
35}
36test "inline variable gets result of const if" {
37 assert(gimme1or2(true) == 1);
38 assert(gimme1or2(false) == 2);
39}
40
41test "static function evaluation" {
42 assert(statically_added_number == 3);
43}
44const statically_added_number = staticAdd(1, 2);
45fn staticAdd(a: i32, b: i32) i32 {
46 return a + b;
47}
48
49test "const expr eval on single expr blocks" {
50 assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
51}
52
53fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
54 const literal = 3;
55
56 const result = if (b) b: {
57 break :b literal;
58 } else b: {
59 break :b x;
60 };
61
62 return result;
63}
64
65test "statically initialized list" {
66 assert(static_point_list[0].x == 1);
67 assert(static_point_list[0].y == 2);
68 assert(static_point_list[1].x == 3);
69 assert(static_point_list[1].y == 4);
70}
71const Point = struct {
72 x: i32,
73 y: i32,
74};
75const static_point_list = []Point{
76 makePoint(1, 2),
77 makePoint(3, 4),
78};
79fn makePoint(x: i32, y: i32) Point {
80 return Point{
81 .x = x,
82 .y = y,
83 };
84}
85
86test "static eval list init" {
87 assert(static_vec3.data[2] == 1.0);
88 assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
89}
90const static_vec3 = vec3(0.0, 0.0, 1.0);
91pub const Vec3 = struct {
92 data: [3]f32,
93};
94pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
95 return Vec3{ .data = []f32{
96 x,
97 y,
98 z,
99 } };
100}
101
102test "constant expressions" {
103 var array: [array_size]u8 = undefined;
104 assert(@sizeOf(@typeOf(array)) == 20);
105}
106const array_size: u8 = 20;
107
108test "constant struct with negation" {
109 assert(vertices[0].x == -0.6);
110}
111const Vertex = struct {
112 x: f32,
113 y: f32,
114 r: f32,
115 g: f32,
116 b: f32,
117};
118const vertices = []Vertex{
119 Vertex{
120 .x = -0.6,
121 .y = -0.4,
122 .r = 1.0,
123 .g = 0.0,
124 .b = 0.0,
125 },
126 Vertex{
127 .x = 0.6,
128 .y = -0.4,
129 .r = 0.0,
130 .g = 1.0,
131 .b = 0.0,
132 },
133 Vertex{
134 .x = 0.0,
135 .y = 0.6,
136 .r = 0.0,
137 .g = 0.0,
138 .b = 1.0,
139 },
140};
141
142test "statically initialized struct" {
143 st_init_str_foo.x += 1;
144 assert(st_init_str_foo.x == 14);
145}
146const StInitStrFoo = struct {
147 x: i32,
148 y: bool,
149};
150var st_init_str_foo = StInitStrFoo{
151 .x = 13,
152 .y = true,
153};
154
155test "statically initalized array literal" {
156 const y: [4]u8 = st_init_arr_lit_x;
157 assert(y[3] == 4);
158}
159const st_init_arr_lit_x = []u8{
160 1,
161 2,
162 3,
163 4,
164};
165
166test "const slice" {
167 comptime {
168 const a = "1234567890";
169 assert(a.len == 10);
170 const b = a[1..2];
171 assert(b.len == 1);
172 assert(b[0] == '2');
173 }
174}
175
176test "try to trick eval with runtime if" {
177 assert(testTryToTrickEvalWithRuntimeIf(true) == 10);
178}
179
180fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
181 comptime var i: usize = 0;
182 inline while (i < 10) : (i += 1) {
183 const result = if (b) false else true;
184 }
185 comptime {
186 return i;
187 }
188}
189
190fn max(comptime T: type, a: T, b: T) T {
191 if (T == bool) {
192 return a or b;
193 } else if (a > b) {
194 return a;
195 } else {
196 return b;
197 }
198}
199fn letsTryToCompareBools(a: bool, b: bool) bool {
200 return max(bool, a, b);
201}
202test "inlined block and runtime block phi" {
203 assert(letsTryToCompareBools(true, true));
204 assert(letsTryToCompareBools(true, false));
205 assert(letsTryToCompareBools(false, true));
206 assert(!letsTryToCompareBools(false, false));
207
208 comptime {
209 assert(letsTryToCompareBools(true, true));
210 assert(letsTryToCompareBools(true, false));
211 assert(letsTryToCompareBools(false, true));
212 assert(!letsTryToCompareBools(false, false));
213 }
214}
215
216const CmdFn = struct {
217 name: []const u8,
218 func: fn (i32) i32,
219};
220
221const cmd_fns = []CmdFn{
222 CmdFn{
223 .name = "one",
224 .func = one,
225 },
226 CmdFn{
227 .name = "two",
228 .func = two,
229 },
230 CmdFn{
231 .name = "three",
232 .func = three,
233 },
234};
235fn one(value: i32) i32 {
236 return value + 1;
237}
238fn two(value: i32) i32 {
239 return value + 2;
240}
241fn three(value: i32) i32 {
242 return value + 3;
243}
244
245fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
246 var result: i32 = start_value;
247 comptime var i = 0;
248 inline while (i < cmd_fns.len) : (i += 1) {
249 if (cmd_fns[i].name[0] == prefix_char) {
250 result = cmd_fns[i].func(result);
251 }
252 }
253 return result;
254}
255
256test "comptime iterate over fn ptr list" {
257 assert(performFn('t', 1) == 6);
258 assert(performFn('o', 0) == 1);
259 assert(performFn('w', 99) == 99);
260}
261
262test "eval @setRuntimeSafety at compile-time" {
263 const result = comptime fnWithSetRuntimeSafety();
264 assert(result == 1234);
265}
266
267fn fnWithSetRuntimeSafety() i32 {
268 @setRuntimeSafety(true);
269 return 1234;
270}
271
272test "eval @setFloatMode at compile-time" {
273 const result = comptime fnWithFloatMode();
274 assert(result == 1234.0);
275}
276
277fn fnWithFloatMode() f32 {
278 @setFloatMode(builtin.FloatMode.Strict);
279 return 1234.0;
280}
281
282const SimpleStruct = struct {
283 field: i32,
284
285 fn method(self: *const SimpleStruct) i32 {
286 return self.field + 3;
287 }
288};
289
290var simple_struct = SimpleStruct{ .field = 1234 };
291
292const bound_fn = simple_struct.method;
293
294test "call method on bound fn referring to var instance" {
295 assert(bound_fn() == 1237);
296}
297
298test "ptr to local array argument at comptime" {
299 comptime {
300 var bytes: [10]u8 = undefined;
301 modifySomeBytes(bytes[0..]);
302 assert(bytes[0] == 'a');
303 assert(bytes[9] == 'b');
304 }
305}
306
307fn modifySomeBytes(bytes: []u8) void {
308 bytes[0] = 'a';
309 bytes[9] = 'b';
310}
311
312test "comparisons 0 <= uint and 0 > uint should be comptime" {
313 testCompTimeUIntComparisons(1234);
314}
315fn testCompTimeUIntComparisons(x: u32) void {
316 if (!(0 <= x)) {
317 @compileError("this condition should be comptime known");
318 }
319 if (0 > x) {
320 @compileError("this condition should be comptime known");
321 }
322 if (!(x >= 0)) {
323 @compileError("this condition should be comptime known");
324 }
325 if (x < 0) {
326 @compileError("this condition should be comptime known");
327 }
328}
329
330test "const ptr to variable data changes at runtime" {
331 assert(foo_ref.name[0] == 'a');
332 foo_ref.name = "b";
333 assert(foo_ref.name[0] == 'b');
334}
335
336const Foo = struct {
337 name: []const u8,
338};
339
340var foo_contents = Foo{ .name = "a" };
341const foo_ref = &foo_contents;
342
343test "create global array with for loop" {
344 assert(global_array[5] == 5 * 5);
345 assert(global_array[9] == 9 * 9);
346}
347
348const global_array = x: {
349 var result: [10]usize = undefined;
350 for (result) |*item, index| {
351 item.* = index * index;
352 }
353 break :x result;
354};
355
356test "compile-time downcast when the bits fit" {
357 comptime {
358 const spartan_count: u16 = 255;
359 const byte = @intCast(u8, spartan_count);
360 assert(byte == 255);
361 }
362}
363
364const hi1 = "hi";
365const hi2 = hi1;
366test "const global shares pointer with other same one" {
367 assertEqualPtrs(&hi1[0], &hi2[0]);
368 comptime assert(&hi1[0] == &hi2[0]);
369}
370fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
371 assert(ptr1 == ptr2);
372}
373
374test "@setEvalBranchQuota" {
375 comptime {
376 // 1001 for the loop and then 1 more for the assert fn call
377 @setEvalBranchQuota(1002);
378 var i = 0;
379 var sum = 0;
380 while (i < 1001) : (i += 1) {
381 sum += i;
382 }
383 assert(sum == 500500);
384 }
385}
386
387// TODO test "float literal at compile time not lossy" {
388// TODO assert(16777216.0 + 1.0 == 16777217.0);
389// TODO assert(9007199254740992.0 + 1.0 == 9007199254740993.0);
390// TODO }
391
392test "f32 at compile time is lossy" {
393 assert(f32(1 << 24) + 1 == 1 << 24);
394}
395
396test "f64 at compile time is lossy" {
397 assert(f64(1 << 53) + 1 == 1 << 53);
398}
399
400test "f128 at compile time is lossy" {
401 assert(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
402}
403
404// TODO need a better implementation of bigfloat_init_bigint
405// assert(f128(1 << 113) == 10384593717069655257060992658440192);
406
407pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
408 return struct {
409 pub const Node = struct {};
410 };
411}
412
413test "string literal used as comptime slice is memoized" {
414 const a = "link";
415 const b = "link";
416 comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
417 comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
418}
419
420test "comptime slice of undefined pointer of length 0" {
421 const slice1 = ([*]i32)(undefined)[0..0];
422 assert(slice1.len == 0);
423 const slice2 = ([*]i32)(undefined)[100..100];
424 assert(slice2.len == 0);
425}
426
427fn copyWithPartialInline(s: []u32, b: []u8) void {
428 comptime var i: usize = 0;
429 inline while (i < 4) : (i += 1) {
430 s[i] = 0;
431 s[i] |= u32(b[i * 4 + 0]) << 24;
432 s[i] |= u32(b[i * 4 + 1]) << 16;
433 s[i] |= u32(b[i * 4 + 2]) << 8;
434 s[i] |= u32(b[i * 4 + 3]) << 0;
435 }
436}
437
438test "binary math operator in partially inlined function" {
439 var s: [4]u32 = undefined;
440 var b: [16]u8 = undefined;
441
442 for (b) |*r, i|
443 r.* = @intCast(u8, i + 1);
444
445 copyWithPartialInline(s[0..], b[0..]);
446 assert(s[0] == 0x1020304);
447 assert(s[1] == 0x5060708);
448 assert(s[2] == 0x90a0b0c);
449 assert(s[3] == 0xd0e0f10);
450}
451
452test "comptime function with the same args is memoized" {
453 comptime {
454 assert(MakeType(i32) == MakeType(i32));
455 assert(MakeType(i32) != MakeType(f64));
456 }
457}
458
459fn MakeType(comptime T: type) type {
460 return struct {
461 field: T,
462 };
463}
464
465test "comptime function with mutable pointer is not memoized" {
466 comptime {
467 var x: i32 = 1;
468 const ptr = &x;
469 increment(ptr);
470 increment(ptr);
471 assert(x == 3);
472 }
473}
474
475fn increment(value: *i32) void {
476 value.* += 1;
477}
478
479fn generateTable(comptime T: type) [1010]T {
480 var res: [1010]T = undefined;
481 var i: usize = 0;
482 while (i < 1010) : (i += 1) {
483 res[i] = @intCast(T, i);
484 }
485 return res;
486}
487
488fn doesAlotT(comptime T: type, value: usize) T {
489 @setEvalBranchQuota(5000);
490 const table = comptime blk: {
491 break :blk generateTable(T);
492 };
493 return table[value];
494}
495
496test "@setEvalBranchQuota at same scope as generic function call" {
497 assert(doesAlotT(u32, 2) == 2);
498}
499
500test "comptime slice of slice preserves comptime var" {
501 comptime {
502 var buff: [10]u8 = undefined;
503 buff[0..][0..][0] = 1;
504 assert(buff[0..][0..][0] == 1);
505 }
506}
507
508test "comptime slice of pointer preserves comptime var" {
509 comptime {
510 var buff: [10]u8 = undefined;
511 var a = buff[0..].ptr;
512 a[0..1][0] = 1;
513 assert(buff[0..][0..][0] == 1);
514 }
515}
516
517const SingleFieldStruct = struct {
518 x: i32,
519
520 fn read_x(self: *const SingleFieldStruct) i32 {
521 return self.x;
522 }
523};
524test "const ptr to comptime mutable data is not memoized" {
525 comptime {
526 var foo = SingleFieldStruct{ .x = 1 };
527 assert(foo.read_x() == 1);
528 foo.x = 2;
529 assert(foo.read_x() == 2);
530 }
531}
532
533test "array concat of slices gives slice" {
534 comptime {
535 var a: []const u8 = "aoeu";
536 var b: []const u8 = "asdf";
537 const c = a ++ b;
538 assert(std.mem.eql(u8, c, "aoeuasdf"));
539 }
540}
541
542test "comptime shlWithOverflow" {
543 const ct_shifted: u64 = comptime amt: {
544 var amt = u64(0);
545 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
546 break :amt amt;
547 };
548
549 const rt_shifted: u64 = amt: {
550 var amt = u64(0);
551 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
552 break :amt amt;
553 };
554
555 assert(ct_shifted == rt_shifted);
556}
557
558test "runtime 128 bit integer division" {
559 var a: u128 = 152313999999999991610955792383;
560 var b: u128 = 10000000000000000000;
561 var c = a / b;
562 assert(c == 15231399999);
563}
564
565pub const Info = struct {
566 version: u8,
567};
568
569pub const diamond_info = Info{ .version = 0 };
570
571test "comptime modification of const struct field" {
572 comptime {
573 var res = diamond_info;
574 res.version = 1;
575 assert(diamond_info.version == 0);
576 assert(res.version == 1);
577 }
578}
579
580test "pointer to type" {
581 comptime {
582 var T: type = i32;
583 assert(T == i32);
584 var ptr = &T;
585 assert(@typeOf(ptr) == *type);
586 ptr.* = f32;
587 assert(T == f32);
588 assert(*T == *f32);
589 }
590}
591
592test "slice of type" {
593 comptime {
594 var types_array = []type{ i32, f64, type };
595 for (types_array) |T, i| {
596 switch (i) {
597 0 => assert(T == i32),
598 1 => assert(T == f64),
599 2 => assert(T == type),
600 else => unreachable,
601 }
602 }
603 for (types_array[0..]) |T, i| {
604 switch (i) {
605 0 => assert(T == i32),
606 1 => assert(T == f64),
607 2 => assert(T == type),
608 else => unreachable,
609 }
610 }
611 }
612}
613
614const Wrapper = struct {
615 T: type,
616};
617
618fn wrap(comptime T: type) Wrapper {
619 return Wrapper{ .T = T };
620}
621
622test "function which returns struct with type field causes implicit comptime" {
623 const ty = wrap(i32).T;
624 assert(ty == i32);
625}
626
627test "call method with comptime pass-by-non-copying-value self parameter" {
628 const S = struct {
629 a: u8,
630
631 fn b(comptime s: @This()) u8 {
632 return s.a;
633 }
634 };
635
636 const s = S{ .a = 2 };
637 var b = s.b();
638 assert(b == 2);
639}
640
641test "@tagName of @typeId" {
642 const str = @tagName(@typeId(u8));
643 assert(std.mem.eql(u8, str, "Int"));
644}
645
646test "setting backward branch quota just before a generic fn call" {
647 @setEvalBranchQuota(1001);
648 loopNTimes(1001);
649}
650
651fn loopNTimes(comptime n: usize) void {
652 comptime var i = 0;
653 inline while (i < n) : (i += 1) {}
654}
655
656test "variable inside inline loop that has different types on different iterations" {
657 testVarInsideInlineLoop(true, u32(42));
658}
659
660fn testVarInsideInlineLoop(args: ...) void {
661 comptime var i = 0;
662 inline while (i < args.len) : (i += 1) {
663 const x = args[i];
664 if (i == 0) assert(x);
665 if (i == 1) assert(x == 42);
666 }
667}
668
669test "inline for with same type but different values" {
670 var res: usize = 0;
671 inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| {
672 var a: T = undefined;
673 res += a.len;
674 }
675 assert(res == 5);
676}
677
678test "refer to the type of a generic function" {
679 const Func = fn (type) void;
680 const f: Func = doNothingWithType;
681 f(i32);
682}
683
684fn doNothingWithType(comptime T: type) void {}
685
686test "zero extend from u0 to u1" {
687 var zero_u0: u0 = 0;
688 var zero_u1: u1 = zero_u0;
689 assert(zero_u1 == 0);
690}
691
692test "bit shift a u1" {
693 var x: u1 = 1;
694 var y = x << 0;
695 assert(y == 1);
696}
697
698test "@intCast to a u0" {
699 var x: u8 = 0;
700 var y: u0 = @intCast(u0, x);
701 assert(y == 0);
702}
703
704test "@bytesToslice on a packed struct" {
705 const F = packed struct {
706 a: u8,
707 };
708
709 var b = [1]u8{9};
710 var f = @bytesToSlice(F, b);
711 assert(f[0].a == 9);
712}
713
714test "comptime pointer cast array and then slice" {
715 const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
716
717 const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
718 const sliceA: []const u8 = ptrA[0..2];
719
720 const ptrB: [*]const u8 = &array;
721 const sliceB: []const u8 = ptrB[0..2];
722
723 assert(sliceA[1] == 2);
724 assert(sliceB[1] == 2);
725}
726
727test "slice bounds in comptime concatenation" {
728 const bs = comptime blk: {
729 const b = c"11";
730 break :blk b[0..1];
731 };
732 const str = "" ++ bs;
733 assert(str.len == 1);
734 assert(std.mem.eql(u8, str, "1"));
735
736 const str2 = bs ++ "";
737 assert(str2.len == 1);
738 assert(std.mem.eql(u8, str2, "1"));
739}
740
741test "comptime bitwise operators" {
742 comptime {
743 assert(3 & 1 == 1);
744 assert(3 & -1 == 3);
745 assert(-3 & -1 == -3);
746 assert(3 | -1 == -1);
747 assert(-3 | -1 == -1);
748 assert(3 ^ -1 == -4);
749 assert(-3 ^ -1 == 2);
750 assert(~i8(-1) == 0);
751 assert(~i128(-1) == 0);
752 assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
753 assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
754 assert(~u128(0) == 0xffffffffffffffffffffffffffffffff);
755 }
756}
757
758test "*align(1) u16 is the same as *align(1:0:2) u16" {
759 comptime {
760 assert(*align(1:0:2) u16 == *align(1) u16);
761 // TODO add parsing support for this syntax
762 //assert(*align(:0:2) u16 == *u16);
763 }
764}
765
766test "array concatenation forces comptime" {
767 var a = oneItem(3) ++ oneItem(4);
768 assert(std.mem.eql(i32, a, []i32{3, 4}));
769}
770
771test "array multiplication forces comptime" {
772 var a = oneItem(3) ** scalar(2);
773 assert(std.mem.eql(i32, a, []i32{3, 3}));
774}
775
776fn oneItem(x: i32) [1]i32 {
777 return []i32{x};
778}
779
780fn scalar(x: u32) u32 {
781 return x;
782}
test/cases/field_parent_ptr.zig deleted-41
......@@ -1,41 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@fieldParentPtr non-first field" {
4 testParentFieldPtr(&foo.c);
5 comptime testParentFieldPtr(&foo.c);
6}
7
8test "@fieldParentPtr first field" {
9 testParentFieldPtrFirst(&foo.a);
10 comptime testParentFieldPtrFirst(&foo.a);
11}
12
13const Foo = struct {
14 a: bool,
15 b: f32,
16 c: i32,
17 d: i32,
18};
19
20const foo = Foo{
21 .a = true,
22 .b = 0.123,
23 .c = 1234,
24 .d = -10,
25};
26
27fn testParentFieldPtr(c: *const i32) void {
28 assert(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 assert(base == &foo);
32 assert(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) void {
36 assert(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 assert(base == &foo);
40 assert(&base.a == a);
41}
test/cases/fn.zig deleted-207
......@@ -1,207 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "params" {
4 assert(testParamsAdd(22, 11) == 33);
5}
6fn testParamsAdd(a: i32, b: i32) i32 {
7 return a + b;
8}
9
10test "local variables" {
11 testLocVars(2);
12}
13fn testLocVars(b: i32) void {
14 const a: i32 = 1;
15 if (a + b != 3) unreachable;
16}
17
18test "void parameters" {
19 voidFun(1, void{}, 2, {});
20}
21fn voidFun(a: i32, b: void, c: i32, d: void) void {
22 const v = b;
23 const vv: void = if (a == 1) v else {};
24 assert(a + c == 3);
25 return vv;
26}
27
28test "mutable local variables" {
29 var zero: i32 = 0;
30 assert(zero == 0);
31
32 var i = i32(0);
33 while (i != 3) {
34 i += 1;
35 }
36 assert(i == 3);
37}
38
39test "separate block scopes" {
40 {
41 const no_conflict: i32 = 5;
42 assert(no_conflict == 5);
43 }
44
45 const c = x: {
46 const no_conflict = i32(10);
47 break :x no_conflict;
48 };
49 assert(c == 10);
50}
51
52test "call function with empty string" {
53 acceptsString("");
54}
55
56fn acceptsString(foo: []u8) void {}
57
58fn @"weird function name"() i32 {
59 return 1234;
60}
61test "weird function name" {
62 assert(@"weird function name"() == 1234);
63}
64
65test "implicit cast function unreachable return" {
66 wantsFnWithVoid(fnWithUnreachable);
67}
68
69fn wantsFnWithVoid(f: fn () void) void {}
70
71fn fnWithUnreachable() noreturn {
72 unreachable;
73}
74
75test "function pointers" {
76 const fns = []@typeOf(fn1){
77 fn1,
78 fn2,
79 fn3,
80 fn4,
81 };
82 for (fns) |f, i| {
83 assert(f() == @intCast(u32, i) + 5);
84 }
85}
86fn fn1() u32 {
87 return 5;
88}
89fn fn2() u32 {
90 return 6;
91}
92fn fn3() u32 {
93 return 7;
94}
95fn fn4() u32 {
96 return 8;
97}
98
99test "inline function call" {
100 assert(@inlineCall(add, 3, 9) == 12);
101}
102
103fn add(a: i32, b: i32) i32 {
104 return a + b;
105}
106
107test "number literal as an argument" {
108 numberLiteralArg(3);
109 comptime numberLiteralArg(3);
110}
111
112fn numberLiteralArg(a: var) void {
113 assert(a == 3);
114}
115
116test "assign inline fn to const variable" {
117 const a = inlineFn;
118 a();
119}
120
121inline fn inlineFn() void {}
122
123test "pass by non-copying value" {
124 assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
125}
126
127const Point = struct {
128 x: i32,
129 y: i32,
130};
131
132fn addPointCoords(pt: Point) i32 {
133 return pt.x + pt.y;
134}
135
136test "pass by non-copying value through var arg" {
137 assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
138}
139
140fn addPointCoordsVar(pt: var) i32 {
141 comptime assert(@typeOf(pt) == Point);
142 return pt.x + pt.y;
143}
144
145test "pass by non-copying value as method" {
146 var pt = Point2{ .x = 1, .y = 2 };
147 assert(pt.addPointCoords() == 3);
148}
149
150const Point2 = struct {
151 x: i32,
152 y: i32,
153
154 fn addPointCoords(self: Point2) i32 {
155 return self.x + self.y;
156 }
157};
158
159test "pass by non-copying value as method, which is generic" {
160 var pt = Point3{ .x = 1, .y = 2 };
161 assert(pt.addPointCoords(i32) == 3);
162}
163
164const Point3 = struct {
165 x: i32,
166 y: i32,
167
168 fn addPointCoords(self: Point3, comptime T: type) i32 {
169 return self.x + self.y;
170 }
171};
172
173test "pass by non-copying value as method, at comptime" {
174 comptime {
175 var pt = Point2{ .x = 1, .y = 2 };
176 assert(pt.addPointCoords() == 3);
177 }
178}
179
180fn outer(y: u32) fn (u32) u32 {
181 const Y = @typeOf(y);
182 const st = struct {
183 fn get(z: u32) u32 {
184 return z + @sizeOf(Y);
185 }
186 };
187 return st.get;
188}
189
190test "return inner function which references comptime variable of outer function" {
191 var func = outer(10);
192 assert(func(3) == 7);
193}
194
195test "extern struct with stdcallcc fn pointer" {
196 const S = extern struct {
197 ptr: stdcallcc fn () i32,
198
199 stdcallcc fn foo() i32 {
200 return 1234;
201 }
202 };
203
204 var s: S = undefined;
205 s.ptr = S.foo;
206 assert(s.ptr() == 1234);
207}
test/cases/fn_in_struct_in_comptime.zig deleted-17
......@@ -1,17 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn get_foo() fn (*u8) usize {
4 comptime {
5 return struct {
6 fn func(ptr: *u8) usize {
7 var u = @ptrToInt(ptr);
8 return u;
9 }
10 }.func;
11 }
12}
13
14test "define a function in an anonymous struct in comptime" {
15 const foo = get_foo();
16 assert(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/cases/for.zig deleted-106
......@@ -1,106 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4
5test "continue in for loop" {
6 const array = []i32{
7 1,
8 2,
9 3,
10 4,
11 5,
12 };
13 var sum: i32 = 0;
14 for (array) |x| {
15 sum += x;
16 if (x < 3) {
17 continue;
18 }
19 break;
20 }
21 if (sum != 6) unreachable;
22}
23
24test "for loop with pointer elem var" {
25 const source = "abcdefg";
26 var target: [source.len]u8 = undefined;
27 mem.copy(u8, target[0..], source);
28 mangleString(target[0..]);
29 assert(mem.eql(u8, target, "bcdefgh"));
30}
31fn mangleString(s: []u8) void {
32 for (s) |*c| {
33 c.* += 1;
34 }
35}
36
37test "basic for loop" {
38 const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
39
40 var buffer: [expected_result.len]u8 = undefined;
41 var buf_index: usize = 0;
42
43 const array = []u8{ 9, 8, 7, 6 };
44 for (array) |item| {
45 buffer[buf_index] = item;
46 buf_index += 1;
47 }
48 for (array) |item, index| {
49 buffer[buf_index] = @intCast(u8, index);
50 buf_index += 1;
51 }
52 const array_ptr = &array;
53 for (array_ptr) |item| {
54 buffer[buf_index] = item;
55 buf_index += 1;
56 }
57 for (array_ptr) |item, index| {
58 buffer[buf_index] = @intCast(u8, index);
59 buf_index += 1;
60 }
61 const unknown_size: []const u8 = array;
62 for (unknown_size) |item| {
63 buffer[buf_index] = item;
64 buf_index += 1;
65 }
66 for (unknown_size) |item, index| {
67 buffer[buf_index] = @intCast(u8, index);
68 buf_index += 1;
69 }
70
71 assert(mem.eql(u8, buffer[0..buf_index], expected_result));
72}
73
74test "break from outer for loop" {
75 testBreakOuter();
76 comptime testBreakOuter();
77}
78
79fn testBreakOuter() void {
80 var array = "aoeu";
81 var count: usize = 0;
82 outer: for (array) |_| {
83 for (array) |_| {
84 count += 1;
85 break :outer;
86 }
87 }
88 assert(count == 1);
89}
90
91test "continue outer for loop" {
92 testContinueOuter();
93 comptime testContinueOuter();
94}
95
96fn testContinueOuter() void {
97 var array = "aoeu";
98 var counter: usize = 0;
99 outer: for (array) |_| {
100 for (array) |_| {
101 counter += 1;
102 continue :outer;
103 }
104 }
105 assert(counter == array.len);
106}
test/cases/generics.zig deleted-151
......@@ -1,151 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "simple generic fn" {
4 assert(max(i32, 3, -1) == 3);
5 assert(max(f32, 0.123, 0.456) == 0.456);
6 assert(add(2, 3) == 5);
7}
8
9fn max(comptime T: type, a: T, b: T) T {
10 return if (a > b) a else b;
11}
12
13fn add(comptime a: i32, b: i32) i32 {
14 return (comptime a) + b;
15}
16
17const the_max = max(u32, 1234, 5678);
18test "compile time generic eval" {
19 assert(the_max == 5678);
20}
21
22fn gimmeTheBigOne(a: u32, b: u32) u32 {
23 return max(u32, a, b);
24}
25
26fn shouldCallSameInstance(a: u32, b: u32) u32 {
27 return max(u32, a, b);
28}
29
30fn sameButWithFloats(a: f64, b: f64) f64 {
31 return max(f64, a, b);
32}
33
34test "fn with comptime args" {
35 assert(gimmeTheBigOne(1234, 5678) == 5678);
36 assert(shouldCallSameInstance(34, 12) == 34);
37 assert(sameButWithFloats(0.43, 0.49) == 0.49);
38}
39
40test "var params" {
41 assert(max_i32(12, 34) == 34);
42 assert(max_f64(1.2, 3.4) == 3.4);
43}
44
45comptime {
46 assert(max_i32(12, 34) == 34);
47 assert(max_f64(1.2, 3.4) == 3.4);
48}
49
50fn max_var(a: var, b: var) @typeOf(a + b) {
51 return if (a > b) a else b;
52}
53
54fn max_i32(a: i32, b: i32) i32 {
55 return max_var(a, b);
56}
57
58fn max_f64(a: f64, b: f64) f64 {
59 return max_var(a, b);
60}
61
62pub fn List(comptime T: type) type {
63 return SmallList(T, 8);
64}
65
66pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
67 return struct {
68 items: []T,
69 length: usize,
70 prealloc_items: [STATIC_SIZE]T,
71 };
72}
73
74test "function with return type type" {
75 var list: List(i32) = undefined;
76 var list2: List(i32) = undefined;
77 list.length = 10;
78 list2.length = 10;
79 assert(list.prealloc_items.len == 8);
80 assert(list2.prealloc_items.len == 8);
81}
82
83test "generic struct" {
84 var a1 = GenNode(i32){
85 .value = 13,
86 .next = null,
87 };
88 var b1 = GenNode(bool){
89 .value = true,
90 .next = null,
91 };
92 assert(a1.value == 13);
93 assert(a1.value == a1.getVal());
94 assert(b1.getVal());
95}
96fn GenNode(comptime T: type) type {
97 return struct {
98 value: T,
99 next: ?*GenNode(T),
100 fn getVal(n: *const GenNode(T)) T {
101 return n.value;
102 }
103 };
104}
105
106test "const decls in struct" {
107 assert(GenericDataThing(3).count_plus_one == 4);
108}
109fn GenericDataThing(comptime count: isize) type {
110 return struct {
111 const count_plus_one = count + 1;
112 };
113}
114
115test "use generic param in generic param" {
116 assert(aGenericFn(i32, 3, 4) == 7);
117}
118fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
119 return a + b;
120}
121
122test "generic fn with implicit cast" {
123 assert(getFirstByte(u8, []u8{13}) == 13);
124 assert(getFirstByte(u16, []u16{
125 0,
126 13,
127 }) == 0);
128}
129fn getByte(ptr: ?*const u8) u8 {
130 return ptr.?.*;
131}
132fn getFirstByte(comptime T: type, mem: []const T) u8 {
133 return getByte(@ptrCast(*const u8, &mem[0]));
134}
135
136const foos = []fn (var) bool{
137 foo1,
138 foo2,
139};
140
141fn foo1(arg: var) bool {
142 return arg;
143}
144fn foo2(arg: var) bool {
145 return !arg;
146}
147
148test "array of generic fns" {
149 assert(foos[0](true));
150 assert(!foos[1](true));
151}
test/cases/if.zig deleted-37
......@@ -1,37 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "if statements" {
4 shouldBeEqual(1, 1);
5 firstEqlThird(2, 1, 2);
6}
7fn shouldBeEqual(a: i32, b: i32) void {
8 if (a != b) {
9 unreachable;
10 } else {
11 return;
12 }
13}
14fn firstEqlThird(a: i32, b: i32, c: i32) void {
15 if (a == b) {
16 unreachable;
17 } else if (b == c) {
18 unreachable;
19 } else if (a == c) {
20 return;
21 } else {
22 unreachable;
23 }
24}
25
26test "else if expression" {
27 assert(elseIfExpressionF(1) == 1);
28}
29fn elseIfExpressionF(c: u8) u8 {
30 if (c == 0) {
31 return 0;
32 } else if (c == 1) {
33 return 1;
34 } else {
35 return u8(2);
36 }
37}
test/cases/import.zig deleted-10
......@@ -1,10 +0,0 @@
1const assert = @import("std").debug.assert;
2const a_namespace = @import("import/a_namespace.zig");
3
4test "call fn via namespace lookup" {
5 assert(a_namespace.foo() == 1234);
6}
7
8test "importing the same thing gives the same import" {
9 assert(@import("std") == @import("std"));
10}
test/cases/import/a_namespace.zig deleted-3
......@@ -1,3 +0,0 @@
1pub fn foo() i32 {
2 return 1234;
3}
test/cases/incomplete_struct_param_tld.zig deleted-30
......@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const A = struct {
4 b: B,
5};
6
7const B = struct {
8 c: C,
9};
10
11const C = struct {
12 x: i32,
13
14 fn d(c: *const C) i32 {
15 return c.x;
16 }
17};
18
19fn foo(a: A) i32 {
20 return a.b.c.d();
21}
22
23test "incomplete struct param top level declaration" {
24 const a = A{
25 .b = B{
26 .c = C{ .x = 13 },
27 },
28 };
29 assert(foo(a) == 13);
30}
test/cases/inttoptr.zig deleted-27
......@@ -1,27 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "casting random address to function pointer" {
6 randomAddressToFunction();
7 comptime randomAddressToFunction();
8}
9
10fn randomAddressToFunction() void {
11 var addr: usize = 0xdeadbeef;
12 var ptr = @intToPtr(fn () void, addr);
13}
14
15test "mutate through ptr initialized with constant intToPtr value" {
16 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
17}
18
19fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
20 const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
21 if (x) {
22 hardCodedP.* = hardCodedP.* | 10;
23 } else {
24 return;
25 }
26}
27
test/cases/ir_block_deps.zig deleted-21
......@@ -1,21 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn foo(id: u64) !i32 {
4 return switch (id) {
5 1 => getErrInt(),
6 2 => {
7 const size = try getErrInt();
8 return try getErrInt();
9 },
10 else => error.ItBroke,
11 };
12}
13
14fn getErrInt() anyerror!i32 {
15 return 0;
16}
17
18test "ir block deps" {
19 assert((foo(1) catch unreachable) == 0);
20 assert((foo(2) catch unreachable) == 0);
21}
test/cases/math.zig deleted-500
......@@ -1,500 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const maxInt = std.math.maxInt;
4const minInt = std.math.minInt;
5
6test "division" {
7 testDivision();
8 comptime testDivision();
9}
10fn testDivision() void {
11 assert(div(u32, 13, 3) == 4);
12 assert(div(f16, 1.0, 2.0) == 0.5);
13 assert(div(f32, 1.0, 2.0) == 0.5);
14
15 assert(divExact(u32, 55, 11) == 5);
16 assert(divExact(i32, -55, 11) == -5);
17 assert(divExact(f16, 55.0, 11.0) == 5.0);
18 assert(divExact(f16, -55.0, 11.0) == -5.0);
19 assert(divExact(f32, 55.0, 11.0) == 5.0);
20 assert(divExact(f32, -55.0, 11.0) == -5.0);
21
22 assert(divFloor(i32, 5, 3) == 1);
23 assert(divFloor(i32, -5, 3) == -2);
24 assert(divFloor(f16, 5.0, 3.0) == 1.0);
25 assert(divFloor(f16, -5.0, 3.0) == -2.0);
26 assert(divFloor(f32, 5.0, 3.0) == 1.0);
27 assert(divFloor(f32, -5.0, 3.0) == -2.0);
28 assert(divFloor(i32, -0x80000000, -2) == 0x40000000);
29 assert(divFloor(i32, 0, -0x80000000) == 0);
30 assert(divFloor(i32, -0x40000001, 0x40000000) == -2);
31 assert(divFloor(i32, -0x80000000, 1) == -0x80000000);
32
33 assert(divTrunc(i32, 5, 3) == 1);
34 assert(divTrunc(i32, -5, 3) == -1);
35 assert(divTrunc(f16, 5.0, 3.0) == 1.0);
36 assert(divTrunc(f16, -5.0, 3.0) == -1.0);
37 assert(divTrunc(f32, 5.0, 3.0) == 1.0);
38 assert(divTrunc(f32, -5.0, 3.0) == -1.0);
39 assert(divTrunc(f64, 5.0, 3.0) == 1.0);
40 assert(divTrunc(f64, -5.0, 3.0) == -1.0);
41
42 comptime {
43 assert(
44 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
45 );
46 assert(
47 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
48 );
49 assert(
50 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
51 );
52 assert(
53 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
54 );
55 assert(
56 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
57 );
58 assert(
59 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
60 );
61 assert(
62 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
63 );
64 }
65}
66fn div(comptime T: type, a: T, b: T) T {
67 return a / b;
68}
69fn divExact(comptime T: type, a: T, b: T) T {
70 return @divExact(a, b);
71}
72fn divFloor(comptime T: type, a: T, b: T) T {
73 return @divFloor(a, b);
74}
75fn divTrunc(comptime T: type, a: T, b: T) T {
76 return @divTrunc(a, b);
77}
78
79test "@addWithOverflow" {
80 var result: u8 = undefined;
81 assert(@addWithOverflow(u8, 250, 100, &result));
82 assert(!@addWithOverflow(u8, 100, 150, &result));
83 assert(result == 250);
84}
85
86// TODO test mulWithOverflow
87// TODO test subWithOverflow
88
89test "@shlWithOverflow" {
90 var result: u16 = undefined;
91 assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
92 assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
93 assert(result == 0b1011111111111100);
94}
95
96test "@clz" {
97 testClz();
98 comptime testClz();
99}
100
101fn testClz() void {
102 assert(clz(u8(0b00001010)) == 4);
103 assert(clz(u8(0b10001010)) == 0);
104 assert(clz(u8(0b00000000)) == 8);
105 assert(clz(u128(0xffffffffffffffff)) == 64);
106 assert(clz(u128(0x10000000000000000)) == 63);
107}
108
109fn clz(x: var) usize {
110 return @clz(x);
111}
112
113test "@ctz" {
114 testCtz();
115 comptime testCtz();
116}
117
118fn testCtz() void {
119 assert(ctz(u8(0b10100000)) == 5);
120 assert(ctz(u8(0b10001010)) == 1);
121 assert(ctz(u8(0b00000000)) == 8);
122}
123
124fn ctz(x: var) usize {
125 return @ctz(x);
126}
127
128test "assignment operators" {
129 var i: u32 = 0;
130 i += 5;
131 assert(i == 5);
132 i -= 2;
133 assert(i == 3);
134 i *= 20;
135 assert(i == 60);
136 i /= 3;
137 assert(i == 20);
138 i %= 11;
139 assert(i == 9);
140 i <<= 1;
141 assert(i == 18);
142 i >>= 2;
143 assert(i == 4);
144 i = 6;
145 i &= 5;
146 assert(i == 4);
147 i ^= 6;
148 assert(i == 2);
149 i = 6;
150 i |= 3;
151 assert(i == 7);
152}
153
154test "three expr in a row" {
155 testThreeExprInARow(false, true);
156 comptime testThreeExprInARow(false, true);
157}
158fn testThreeExprInARow(f: bool, t: bool) void {
159 assertFalse(f or f or f);
160 assertFalse(t and t and f);
161 assertFalse(1 | 2 | 4 != 7);
162 assertFalse(3 ^ 6 ^ 8 != 13);
163 assertFalse(7 & 14 & 28 != 4);
164 assertFalse(9 << 1 << 2 != 9 << 3);
165 assertFalse(90 >> 1 >> 2 != 90 >> 3);
166 assertFalse(100 - 1 + 1000 != 1099);
167 assertFalse(5 * 4 / 2 % 3 != 1);
168 assertFalse(i32(i32(5)) != 5);
169 assertFalse(!!false);
170 assertFalse(i32(7) != --(i32(7)));
171}
172fn assertFalse(b: bool) void {
173 assert(!b);
174}
175
176test "const number literal" {
177 const one = 1;
178 const eleven = ten + one;
179
180 assert(eleven == 11);
181}
182const ten = 10;
183
184test "unsigned wrapping" {
185 testUnsignedWrappingEval(maxInt(u32));
186 comptime testUnsignedWrappingEval(maxInt(u32));
187}
188fn testUnsignedWrappingEval(x: u32) void {
189 const zero = x +% 1;
190 assert(zero == 0);
191 const orig = zero -% 1;
192 assert(orig == maxInt(u32));
193}
194
195test "signed wrapping" {
196 testSignedWrappingEval(maxInt(i32));
197 comptime testSignedWrappingEval(maxInt(i32));
198}
199fn testSignedWrappingEval(x: i32) void {
200 const min_val = x +% 1;
201 assert(min_val == minInt(i32));
202 const max_val = min_val -% 1;
203 assert(max_val == maxInt(i32));
204}
205
206test "negation wrapping" {
207 testNegationWrappingEval(minInt(i16));
208 comptime testNegationWrappingEval(minInt(i16));
209}
210fn testNegationWrappingEval(x: i16) void {
211 assert(x == -32768);
212 const neg = -%x;
213 assert(neg == -32768);
214}
215
216test "unsigned 64-bit division" {
217 test_u64_div();
218 comptime test_u64_div();
219}
220fn test_u64_div() void {
221 const result = divWithResult(1152921504606846976, 34359738365);
222 assert(result.quotient == 33554432);
223 assert(result.remainder == 100663296);
224}
225fn divWithResult(a: u64, b: u64) DivResult {
226 return DivResult{
227 .quotient = a / b,
228 .remainder = a % b,
229 };
230}
231const DivResult = struct {
232 quotient: u64,
233 remainder: u64,
234};
235
236test "binary not" {
237 assert(comptime x: {
238 break :x ~u16(0b1010101010101010) == 0b0101010101010101;
239 });
240 assert(comptime x: {
241 break :x ~u64(2147483647) == 18446744071562067968;
242 });
243 testBinaryNot(0b1010101010101010);
244}
245
246fn testBinaryNot(x: u16) void {
247 assert(~x == 0b0101010101010101);
248}
249
250test "small int addition" {
251 var x: @IntType(false, 2) = 0;
252 assert(x == 0);
253
254 x += 1;
255 assert(x == 1);
256
257 x += 1;
258 assert(x == 2);
259
260 x += 1;
261 assert(x == 3);
262
263 var result: @typeOf(x) = 3;
264 assert(@addWithOverflow(@typeOf(x), x, 1, &result));
265
266 assert(result == 0);
267}
268
269test "float equality" {
270 const x: f64 = 0.012;
271 const y: f64 = x + 1.0;
272
273 testFloatEqualityImpl(x, y);
274 comptime testFloatEqualityImpl(x, y);
275}
276
277fn testFloatEqualityImpl(x: f64, y: f64) void {
278 const y2 = x + 1.0;
279 assert(y == y2);
280}
281
282test "allow signed integer division/remainder when values are comptime known and positive or exact" {
283 assert(5 / 3 == 1);
284 assert(-5 / -3 == 1);
285 assert(-6 / 3 == -2);
286
287 assert(5 % 3 == 2);
288 assert(-6 % 3 == 0);
289}
290
291test "hex float literal parsing" {
292 comptime assert(0x1.0 == 1.0);
293}
294
295test "quad hex float literal parsing in range" {
296 const a = 0x1.af23456789bbaaab347645365cdep+5;
297 const b = 0x1.dedafcff354b6ae9758763545432p-9;
298 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
299 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
300}
301
302test "quad hex float literal parsing accurate" {
303 const a: f128 = 0x1.1111222233334444555566667777p+0;
304
305 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
306 const expected: u128 = 0x3fff1111222233334444555566667777;
307 assert(@bitCast(u128, a) == expected);
308}
309
310test "hex float literal within range" {
311 const a = 0x1.0p16383;
312 const b = 0x0.1p16387;
313 const c = 0x1.0p-16382;
314}
315
316test "truncating shift left" {
317 testShlTrunc(maxInt(u16));
318 comptime testShlTrunc(maxInt(u16));
319}
320fn testShlTrunc(x: u16) void {
321 const shifted = x << 1;
322 assert(shifted == 65534);
323}
324
325test "truncating shift right" {
326 testShrTrunc(maxInt(u16));
327 comptime testShrTrunc(maxInt(u16));
328}
329fn testShrTrunc(x: u16) void {
330 const shifted = x >> 1;
331 assert(shifted == 32767);
332}
333
334test "exact shift left" {
335 testShlExact(0b00110101);
336 comptime testShlExact(0b00110101);
337}
338fn testShlExact(x: u8) void {
339 const shifted = @shlExact(x, 2);
340 assert(shifted == 0b11010100);
341}
342
343test "exact shift right" {
344 testShrExact(0b10110100);
345 comptime testShrExact(0b10110100);
346}
347fn testShrExact(x: u8) void {
348 const shifted = @shrExact(x, 2);
349 assert(shifted == 0b00101101);
350}
351
352test "comptime_int addition" {
353 comptime {
354 assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
355 assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
356 }
357}
358
359test "comptime_int multiplication" {
360 comptime {
361 assert(
362 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
363 );
364 assert(
365 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
366 );
367 }
368}
369
370test "comptime_int shifting" {
371 comptime {
372 assert((u128(1) << 127) == 0x80000000000000000000000000000000);
373 }
374}
375
376test "comptime_int multi-limb shift and mask" {
377 comptime {
378 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
379
380 assert(u32(a & 0xffffffff) == 0xaaaaaaab);
381 a >>= 32;
382 assert(u32(a & 0xffffffff) == 0xeeeeeeef);
383 a >>= 32;
384 assert(u32(a & 0xffffffff) == 0xa0000001);
385 a >>= 32;
386 assert(u32(a & 0xffffffff) == 0xefffffff);
387 a >>= 32;
388
389 assert(a == 0);
390 }
391}
392
393test "comptime_int multi-limb partial shift right" {
394 comptime {
395 var a = 0x1ffffffffeeeeeeee;
396 a >>= 16;
397 assert(a == 0x1ffffffffeeee);
398 }
399}
400
401test "xor" {
402 test_xor();
403 comptime test_xor();
404}
405
406fn test_xor() void {
407 assert(0xFF ^ 0x00 == 0xFF);
408 assert(0xF0 ^ 0x0F == 0xFF);
409 assert(0xFF ^ 0xF0 == 0x0F);
410 assert(0xFF ^ 0x0F == 0xF0);
411 assert(0xFF ^ 0xFF == 0x00);
412}
413
414test "comptime_int xor" {
415 comptime {
416 assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
417 assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
418 assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
419 assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
420 assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
421 assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
422 assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
423 assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
424 }
425}
426
427test "f128" {
428 test_f128();
429 comptime test_f128();
430}
431
432fn make_f128(x: f128) f128 {
433 return x;
434}
435
436fn test_f128() void {
437 assert(@sizeOf(f128) == 16);
438 assert(make_f128(1.0) == 1.0);
439 assert(make_f128(1.0) != 1.1);
440 assert(make_f128(1.0) > 0.9);
441 assert(make_f128(1.0) >= 0.9);
442 assert(make_f128(1.0) >= 1.0);
443 should_not_be_zero(1.0);
444}
445
446fn should_not_be_zero(x: f128) void {
447 assert(x != 0.0);
448}
449
450test "comptime float rem int" {
451 comptime {
452 var x = f32(1) % 2;
453 assert(x == 1.0);
454 }
455}
456
457test "remainder division" {
458 comptime remdiv(f16);
459 comptime remdiv(f32);
460 comptime remdiv(f64);
461 comptime remdiv(f128);
462 remdiv(f16);
463 remdiv(f64);
464 remdiv(f128);
465}
466
467fn remdiv(comptime T: type) void {
468 assert(T(1) == T(1) % T(2));
469 assert(T(1) == T(7) % T(3));
470}
471
472test "@sqrt" {
473 testSqrt(f64, 12.0);
474 comptime testSqrt(f64, 12.0);
475 testSqrt(f32, 13.0);
476 comptime testSqrt(f32, 13.0);
477 testSqrt(f16, 13.0);
478 comptime testSqrt(f16, 13.0);
479
480 const x = 14.0;
481 const y = x * x;
482 const z = @sqrt(@typeOf(y), y);
483 comptime assert(z == x);
484}
485
486fn testSqrt(comptime T: type, x: T) void {
487 assert(@sqrt(T, x * x) == x);
488}
489
490test "comptime_int param and return" {
491 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
492 assert(a == 137114567242441932203689521744947848950);
493
494 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
495 assert(b == 985095453608931032642182098849559179469148836107390954364380);
496}
497
498fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
499 return a + b;
500}
test/cases/merge_error_sets.zig deleted-21
......@@ -1,21 +0,0 @@
1const A = error{
2 FileNotFound,
3 NotDir,
4};
5const B = error{OutOfMemory};
6
7const C = A || B;
8
9fn foo() C!void {
10 return error.NotDir;
11}
12
13test "merge error sets" {
14 if (foo()) {
15 @panic("unexpected");
16 } else |err| switch (err) {
17 error.OutOfMemory => @panic("unexpected"),
18 error.FileNotFound => @panic("unexpected"),
19 error.NotDir => {},
20 }
21}
test/cases/misc.zig deleted-681
......@@ -1,681 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const cstr = std.cstr;
5const builtin = @import("builtin");
6const maxInt = std.math.maxInt;
7
8// normal comment
9
10/// this is a documentation comment
11/// doc comment line 2
12fn emptyFunctionWithComments() void {}
13
14test "empty function with comments" {
15 emptyFunctionWithComments();
16}
17
18comptime {
19 @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
20}
21
22extern fn disabledExternFn() void {}
23
24test "call disabled extern fn" {
25 disabledExternFn();
26}
27
28test "@IntType builtin" {
29 assert(@IntType(true, 8) == i8);
30 assert(@IntType(true, 16) == i16);
31 assert(@IntType(true, 32) == i32);
32 assert(@IntType(true, 64) == i64);
33
34 assert(@IntType(false, 8) == u8);
35 assert(@IntType(false, 16) == u16);
36 assert(@IntType(false, 32) == u32);
37 assert(@IntType(false, 64) == u64);
38
39 assert(i8.bit_count == 8);
40 assert(i16.bit_count == 16);
41 assert(i32.bit_count == 32);
42 assert(i64.bit_count == 64);
43
44 assert(i8.is_signed);
45 assert(i16.is_signed);
46 assert(i32.is_signed);
47 assert(i64.is_signed);
48 assert(isize.is_signed);
49
50 assert(!u8.is_signed);
51 assert(!u16.is_signed);
52 assert(!u32.is_signed);
53 assert(!u64.is_signed);
54 assert(!usize.is_signed);
55}
56
57test "floating point primitive bit counts" {
58 assert(f16.bit_count == 16);
59 assert(f32.bit_count == 32);
60 assert(f64.bit_count == 64);
61}
62
63test "short circuit" {
64 testShortCircuit(false, true);
65 comptime testShortCircuit(false, true);
66}
67
68fn testShortCircuit(f: bool, t: bool) void {
69 var hit_1 = f;
70 var hit_2 = f;
71 var hit_3 = f;
72 var hit_4 = f;
73
74 if (t or x: {
75 assert(f);
76 break :x f;
77 }) {
78 hit_1 = t;
79 }
80 if (f or x: {
81 hit_2 = t;
82 break :x f;
83 }) {
84 assert(f);
85 }
86
87 if (t and x: {
88 hit_3 = t;
89 break :x f;
90 }) {
91 assert(f);
92 }
93 if (f and x: {
94 assert(f);
95 break :x f;
96 }) {
97 assert(f);
98 } else {
99 hit_4 = t;
100 }
101 assert(hit_1);
102 assert(hit_2);
103 assert(hit_3);
104 assert(hit_4);
105}
106
107test "truncate" {
108 assert(testTruncate(0x10fd) == 0xfd);
109}
110fn testTruncate(x: u32) u8 {
111 return @truncate(u8, x);
112}
113
114fn first4KeysOfHomeRow() []const u8 {
115 return "aoeu";
116}
117
118test "return string from function" {
119 assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
120}
121
122const g1: i32 = 1233 + 1;
123var g2: i32 = 0;
124
125test "global variables" {
126 assert(g2 == 0);
127 g2 = g1;
128 assert(g2 == 1234);
129}
130
131test "memcpy and memset intrinsics" {
132 var foo: [20]u8 = undefined;
133 var bar: [20]u8 = undefined;
134
135 @memset(foo[0..].ptr, 'A', foo.len);
136 @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
137
138 if (bar[11] != 'A') unreachable;
139}
140
141test "builtin static eval" {
142 const x: i32 = comptime x: {
143 break :x 1 + 2 + 3;
144 };
145 assert(x == comptime 6);
146}
147
148test "slicing" {
149 var array: [20]i32 = undefined;
150
151 array[5] = 1234;
152
153 var slice = array[5..10];
154
155 if (slice.len != 5) unreachable;
156
157 const ptr = &slice[0];
158 if (ptr.* != 1234) unreachable;
159
160 var slice_rest = array[10..];
161 if (slice_rest.len != 10) unreachable;
162}
163
164test "constant equal function pointers" {
165 const alias = emptyFn;
166 assert(comptime x: {
167 break :x emptyFn == alias;
168 });
169}
170
171fn emptyFn() void {}
172
173test "hex escape" {
174 assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
175}
176
177test "string concatenation" {
178 assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
179}
180
181test "array mult operator" {
182 assert(mem.eql(u8, "ab" ** 5, "ababababab"));
183}
184
185test "string escapes" {
186 assert(mem.eql(u8, "\"", "\x22"));
187 assert(mem.eql(u8, "\'", "\x27"));
188 assert(mem.eql(u8, "\n", "\x0a"));
189 assert(mem.eql(u8, "\r", "\x0d"));
190 assert(mem.eql(u8, "\t", "\x09"));
191 assert(mem.eql(u8, "\\", "\x5c"));
192 assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
193}
194
195test "multiline string" {
196 const s1 =
197 \\one
198 \\two)
199 \\three
200 ;
201 const s2 = "one\ntwo)\nthree";
202 assert(mem.eql(u8, s1, s2));
203}
204
205test "multiline C string" {
206 const s1 =
207 c\\one
208 c\\two)
209 c\\three
210 ;
211 const s2 = c"one\ntwo)\nthree";
212 assert(cstr.cmp(s1, s2) == 0);
213}
214
215test "type equality" {
216 assert(*const u8 != *u8);
217}
218
219const global_a: i32 = 1234;
220const global_b: *const i32 = &global_a;
221const global_c: *const f32 = @ptrCast(*const f32, global_b);
222test "compile time global reinterpret" {
223 const d = @ptrCast(*const i32, global_c);
224 assert(d.* == 1234);
225}
226
227test "explicit cast maybe pointers" {
228 const a: ?*i32 = undefined;
229 const b: ?*f32 = @ptrCast(?*f32, a);
230}
231
232test "generic malloc free" {
233 const a = memAlloc(u8, 10) catch unreachable;
234 memFree(u8, a);
235}
236var some_mem: [100]u8 = undefined;
237fn memAlloc(comptime T: type, n: usize) anyerror![]T {
238 return @ptrCast([*]T, &some_mem[0])[0..n];
239}
240fn memFree(comptime T: type, memory: []T) void {}
241
242test "cast undefined" {
243 const array: [100]u8 = undefined;
244 const slice = ([]const u8)(array);
245 testCastUndefined(slice);
246}
247fn testCastUndefined(x: []const u8) void {}
248
249test "cast small unsigned to larger signed" {
250 assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
251 assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
252}
253fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
254 return x;
255}
256fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
257 return x;
258}
259
260test "implicit cast after unreachable" {
261 assert(outer() == 1234);
262}
263fn inner() i32 {
264 return 1234;
265}
266fn outer() i64 {
267 return inner();
268}
269
270test "pointer dereferencing" {
271 var x = i32(3);
272 const y = &x;
273
274 y.* += 1;
275
276 assert(x == 4);
277 assert(y.* == 4);
278}
279
280test "call result of if else expression" {
281 assert(mem.eql(u8, f2(true), "a"));
282 assert(mem.eql(u8, f2(false), "b"));
283}
284fn f2(x: bool) []const u8 {
285 return (if (x) fA else fB)();
286}
287fn fA() []const u8 {
288 return "a";
289}
290fn fB() []const u8 {
291 return "b";
292}
293
294test "const expression eval handling of variables" {
295 var x = true;
296 while (x) {
297 x = false;
298 }
299}
300
301test "constant enum initialization with differing sizes" {
302 test3_1(test3_foo);
303 test3_2(test3_bar);
304}
305const Test3Foo = union(enum) {
306 One: void,
307 Two: f32,
308 Three: Test3Point,
309};
310const Test3Point = struct {
311 x: i32,
312 y: i32,
313};
314const test3_foo = Test3Foo{
315 .Three = Test3Point{
316 .x = 3,
317 .y = 4,
318 },
319};
320const test3_bar = Test3Foo{ .Two = 13 };
321fn test3_1(f: Test3Foo) void {
322 switch (f) {
323 Test3Foo.Three => |pt| {
324 assert(pt.x == 3);
325 assert(pt.y == 4);
326 },
327 else => unreachable,
328 }
329}
330fn test3_2(f: Test3Foo) void {
331 switch (f) {
332 Test3Foo.Two => |x| {
333 assert(x == 13);
334 },
335 else => unreachable,
336 }
337}
338
339test "character literals" {
340 assert('\'' == single_quote);
341}
342const single_quote = '\'';
343
344test "take address of parameter" {
345 testTakeAddressOfParameter(12.34);
346}
347fn testTakeAddressOfParameter(f: f32) void {
348 const f_ptr = &f;
349 assert(f_ptr.* == 12.34);
350}
351
352test "pointer comparison" {
353 const a = ([]const u8)("a");
354 const b = &a;
355 assert(ptrEql(b, b));
356}
357fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
358 return a == b;
359}
360
361test "C string concatenation" {
362 const a = c"OK" ++ c" IT " ++ c"WORKED";
363 const b = c"OK IT WORKED";
364
365 const len = cstr.len(b);
366 const len_with_null = len + 1;
367 {
368 var i: u32 = 0;
369 while (i < len_with_null) : (i += 1) {
370 assert(a[i] == b[i]);
371 }
372 }
373 assert(a[len] == 0);
374 assert(b[len] == 0);
375}
376
377test "cast slice to u8 slice" {
378 assert(@sizeOf(i32) == 4);
379 var big_thing_array = []i32{
380 1,
381 2,
382 3,
383 4,
384 };
385 const big_thing_slice: []i32 = big_thing_array[0..];
386 const bytes = @sliceToBytes(big_thing_slice);
387 assert(bytes.len == 4 * 4);
388 bytes[4] = 0;
389 bytes[5] = 0;
390 bytes[6] = 0;
391 bytes[7] = 0;
392 assert(big_thing_slice[1] == 0);
393 const big_thing_again = @bytesToSlice(i32, bytes);
394 assert(big_thing_again[2] == 3);
395 big_thing_again[2] = -1;
396 assert(bytes[8] == maxInt(u8));
397 assert(bytes[9] == maxInt(u8));
398 assert(bytes[10] == maxInt(u8));
399 assert(bytes[11] == maxInt(u8));
400}
401
402test "pointer to void return type" {
403 testPointerToVoidReturnType() catch unreachable;
404}
405fn testPointerToVoidReturnType() anyerror!void {
406 const a = testPointerToVoidReturnType2();
407 return a.*;
408}
409const test_pointer_to_void_return_type_x = void{};
410fn testPointerToVoidReturnType2() *const void {
411 return &test_pointer_to_void_return_type_x;
412}
413
414test "non const ptr to aliased type" {
415 const int = i32;
416 assert(?*int == ?*i32);
417}
418
419test "array 2D const double ptr" {
420 const rect_2d_vertexes = [][1]f32{
421 []f32{1.0},
422 []f32{2.0},
423 };
424 testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
425}
426
427fn testArray2DConstDoublePtr(ptr: *const f32) void {
428 const ptr2 = @ptrCast([*]const f32, ptr);
429 assert(ptr2[0] == 1.0);
430 assert(ptr2[1] == 2.0);
431}
432
433const Tid = builtin.TypeId;
434const AStruct = struct {
435 x: i32,
436};
437const AnEnum = enum {
438 One,
439 Two,
440};
441const AUnionEnum = union(enum) {
442 One: i32,
443 Two: void,
444};
445const AUnion = union {
446 One: void,
447 Two: void,
448};
449
450test "@typeId" {
451 comptime {
452 assert(@typeId(type) == Tid.Type);
453 assert(@typeId(void) == Tid.Void);
454 assert(@typeId(bool) == Tid.Bool);
455 assert(@typeId(noreturn) == Tid.NoReturn);
456 assert(@typeId(i8) == Tid.Int);
457 assert(@typeId(u8) == Tid.Int);
458 assert(@typeId(i64) == Tid.Int);
459 assert(@typeId(u64) == Tid.Int);
460 assert(@typeId(f32) == Tid.Float);
461 assert(@typeId(f64) == Tid.Float);
462 assert(@typeId(*f32) == Tid.Pointer);
463 assert(@typeId([2]u8) == Tid.Array);
464 assert(@typeId(AStruct) == Tid.Struct);
465 assert(@typeId(@typeOf(1)) == Tid.ComptimeInt);
466 assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
467 assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
468 assert(@typeId(@typeOf(null)) == Tid.Null);
469 assert(@typeId(?i32) == Tid.Optional);
470 assert(@typeId(anyerror!i32) == Tid.ErrorUnion);
471 assert(@typeId(anyerror) == Tid.ErrorSet);
472 assert(@typeId(AnEnum) == Tid.Enum);
473 assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
474 assert(@typeId(AUnionEnum) == Tid.Union);
475 assert(@typeId(AUnion) == Tid.Union);
476 assert(@typeId(fn () void) == Tid.Fn);
477 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
478 // TODO bound fn
479 // TODO arg tuple
480 // TODO opaque
481 }
482}
483
484test "@typeName" {
485 const Struct = struct {};
486 const Union = union {
487 unused: u8,
488 };
489 const Enum = enum {
490 Unused,
491 };
492 comptime {
493 assert(mem.eql(u8, @typeName(i64), "i64"));
494 assert(mem.eql(u8, @typeName(*usize), "*usize"));
495 // https://github.com/ziglang/zig/issues/675
496 assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
497 assert(mem.eql(u8, @typeName(Struct), "Struct"));
498 assert(mem.eql(u8, @typeName(Union), "Union"));
499 assert(mem.eql(u8, @typeName(Enum), "Enum"));
500 }
501}
502
503fn TypeFromFn(comptime T: type) type {
504 return struct {};
505}
506
507test "volatile load and store" {
508 var number: i32 = 1234;
509 const ptr = (*volatile i32)(&number);
510 ptr.* += 1;
511 assert(ptr.* == 1235);
512}
513
514test "slice string literal has type []const u8" {
515 comptime {
516 assert(@typeOf("aoeu"[0..]) == []const u8);
517 const array = []i32{
518 1,
519 2,
520 3,
521 4,
522 };
523 assert(@typeOf(array[0..]) == []const i32);
524 }
525}
526
527test "global variable initialized to global variable array element" {
528 assert(global_ptr == &gdt[0]);
529}
530const GDTEntry = struct {
531 field: i32,
532};
533var gdt = []GDTEntry{
534 GDTEntry{ .field = 1 },
535 GDTEntry{ .field = 2 },
536};
537var global_ptr = &gdt[0];
538
539// can't really run this test but we can make sure it has no compile error
540// and generates code
541const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
542export fn writeToVRam() void {
543 vram[0] = 'X';
544}
545
546test "pointer child field" {
547 assert((*u32).Child == u32);
548}
549
550const OpaqueA = @OpaqueType();
551const OpaqueB = @OpaqueType();
552test "@OpaqueType" {
553 assert(*OpaqueA != *OpaqueB);
554 assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
555 assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
556}
557
558test "variable is allowed to be a pointer to an opaque type" {
559 var x: i32 = 1234;
560 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
561}
562fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
563 var a = ptr;
564 return a;
565}
566
567test "comptime if inside runtime while which unconditionally breaks" {
568 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
569 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
570}
571fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
572 while (cond) {
573 if (false) {}
574 break;
575 }
576}
577
578test "implicit comptime while" {
579 while (false) {
580 @compileError("bad");
581 }
582}
583
584test "struct inside function" {
585 testStructInFn();
586 comptime testStructInFn();
587}
588
589fn testStructInFn() void {
590 const BlockKind = u32;
591
592 const Block = struct {
593 kind: BlockKind,
594 };
595
596 var block = Block{ .kind = 1234 };
597
598 block.kind += 1;
599
600 assert(block.kind == 1235);
601}
602
603fn fnThatClosesOverLocalConst() type {
604 const c = 1;
605 return struct {
606 fn g() i32 {
607 return c;
608 }
609 };
610}
611
612test "function closes over local const" {
613 const x = fnThatClosesOverLocalConst().g();
614 assert(x == 1);
615}
616
617test "cold function" {
618 thisIsAColdFn();
619 comptime thisIsAColdFn();
620}
621
622fn thisIsAColdFn() void {
623 @setCold(true);
624}
625
626const PackedStruct = packed struct {
627 a: u8,
628 b: u8,
629};
630const PackedUnion = packed union {
631 a: u8,
632 b: u32,
633};
634const PackedEnum = packed enum {
635 A,
636 B,
637};
638
639test "packed struct, enum, union parameters in extern function" {
640 testPackedStuff(&(PackedStruct{
641 .a = 1,
642 .b = 2,
643 }), &(PackedUnion{ .a = 1 }), PackedEnum.A);
644}
645
646export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
647
648test "slicing zero length array" {
649 const s1 = ""[0..];
650 const s2 = ([]u32{})[0..];
651 assert(s1.len == 0);
652 assert(s2.len == 0);
653 assert(mem.eql(u8, s1, ""));
654 assert(mem.eql(u32, s2, []u32{}));
655}
656
657const addr1 = @ptrCast(*const u8, emptyFn);
658test "comptime cast fn to ptr" {
659 const addr2 = @ptrCast(*const u8, emptyFn);
660 comptime assert(addr1 == addr2);
661}
662
663test "equality compare fn ptrs" {
664 var a = emptyFn;
665 assert(a == a);
666}
667
668test "self reference through fn ptr field" {
669 const S = struct {
670 const A = struct {
671 f: fn (A) u8,
672 };
673
674 fn foo(a: A) u8 {
675 return 12;
676 }
677 };
678 var a: S.A = undefined;
679 a.f = S.foo;
680 assert(a.f(a) == 12);
681}
test/cases/namespace_depends_on_compile_var/a.zig deleted-1
......@@ -1 +0,0 @@
1pub const a_bool = true;
test/cases/namespace_depends_on_compile_var/b.zig deleted-1
......@@ -1 +0,0 @@
1pub const a_bool = false;
test/cases/namespace_depends_on_compile_var/index.zig deleted-14
......@@ -1,14 +0,0 @@
1const builtin = @import("builtin");
2const assert = @import("std").debug.assert;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 assert(some_namespace.a_bool);
7 } else {
8 assert(!some_namespace.a_bool);
9 }
10}
11const some_namespace = switch (builtin.os) {
12 builtin.Os.linux => @import("a.zig"),
13 else => @import("b.zig"),
14};
test/cases/new_stack_call.zig deleted-26
......@@ -1,26 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4var new_stack_bytes: [1024]u8 = undefined;
5
6test "calling a function with a new stack" {
7 const arg = 1234;
8
9 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
10 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
11 _ = targetFunction(arg);
12
13 assert(arg == 1234);
14 assert(a < b);
15}
16
17fn targetFunction(x: i32) usize {
18 assert(x == 1234);
19
20 var local_variable: i32 = 42;
21 const ptr = &local_variable;
22 ptr.* += 1;
23
24 assert(local_variable == 43);
25 return @ptrToInt(ptr);
26}
test/cases/null.zig deleted-162
......@@ -1,162 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "optional type" {
4 const x: ?bool = true;
5
6 if (x) |y| {
7 if (y) {
8 // OK
9 } else {
10 unreachable;
11 }
12 } else {
13 unreachable;
14 }
15
16 const next_x: ?i32 = null;
17
18 const z = next_x orelse 1234;
19
20 assert(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 assert(num == 13);
27}
28
29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;
31
32 if (maybe_bool) |*b| {
33 b.* = false;
34 }
35
36 assert(maybe_bool.? == false);
37}
38
39test "rhs maybe unwrap return" {
40 const x: ?bool = true;
41 const y = x orelse return;
42}
43
44test "maybe return" {
45 maybeReturnImpl();
46 comptime maybeReturnImpl();
47}
48
49fn maybeReturnImpl() void {
50 assert(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 assert(!foo(1234).?);
53}
54
55fn foo(x: ?i32) ?bool {
56 const value = x orelse return null;
57 return value > 1234;
58}
59
60test "if var maybe pointer" {
61 assert(shouldBeAPlus1(Particle{
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
67}
68fn shouldBeAPlus1(p: Particle) u64 {
69 var maybe_particle: ?Particle = p;
70 if (maybe_particle) |*particle| {
71 particle.a += 1;
72 }
73 if (maybe_particle) |particle| {
74 return particle.a;
75 }
76 return 0;
77}
78const Particle = struct {
79 a: u64,
80 b: u64,
81 c: u64,
82 d: u64,
83};
84
85test "null literal outside function" {
86 const is_null = here_is_a_null_literal.context == null;
87 assert(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 assert(!is_non_null);
91}
92const SillyStruct = struct {
93 context: ?i32,
94};
95const here_is_a_null_literal = SillyStruct{ .context = null };
96
97test "test null runtime" {
98 testTestNullRuntime(null);
99}
100fn testTestNullRuntime(x: ?i32) void {
101 assert(x == null);
102 assert(!(x != null));
103}
104
105test "optional void" {
106 optionalVoidImpl();
107 comptime optionalVoidImpl();
108}
109
110fn optionalVoidImpl() void {
111 assert(bar(null) == null);
112 assert(bar({}) != null);
113}
114
115fn bar(x: ?void) ?void {
116 if (x) |_| {
117 return {};
118 } else {
119 return null;
120 }
121}
122
123const StructWithOptional = struct {
124 field: ?i32,
125};
126
127var struct_with_optional: StructWithOptional = undefined;
128
129test "unwrap optional which is field of global var" {
130 struct_with_optional.field = null;
131 if (struct_with_optional.field) |payload| {
132 unreachable;
133 }
134 struct_with_optional.field = 1234;
135 if (struct_with_optional.field) |payload| {
136 assert(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 assert(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 assert(opt_type_struct.t != null and opt_type_struct.t.? == u8);
151 }
152}
153
154const StructWithOptionalType = struct {
155 t: ?type,
156};
157
158test "optional pointer to 0 bit type null value at runtime" {
159 const EmptyStruct = struct {};
160 var x: ?*EmptyStruct = null;
161 assert(x == null);
162}
test/cases/optional.zig deleted-30
......@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3pub const EmptyStruct = struct {};
4
5test "optional pointer to size zero struct" {
6 var e = EmptyStruct{};
7 var o: ?*EmptyStruct = &e;
8 assert(o != null);
9}
10
11test "equality compare nullable pointers" {
12 testNullPtrsEql();
13 comptime testNullPtrsEql();
14}
15
16fn testNullPtrsEql() void {
17 var number: i32 = 1234;
18
19 var x: ?*i32 = null;
20 var y: ?*i32 = null;
21 assert(x == y);
22 y = &number;
23 assert(x != y);
24 assert(x != &number);
25 assert(&number != x);
26 x = &number;
27 assert(x == y);
28 assert(x == &number);
29 assert(&number == x);
30}
test/cases/pointers.zig deleted-44
......@@ -1,44 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "dereference pointer" {
5 comptime testDerefPtr();
6 testDerefPtr();
7}
8
9fn testDerefPtr() void {
10 var x: i32 = 1234;
11 var y = &x;
12 y.* += 1;
13 assert(x == 1235);
14}
15
16test "pointer arithmetic" {
17 var ptr = c"abcd";
18
19 assert(ptr[0] == 'a');
20 ptr += 1;
21 assert(ptr[0] == 'b');
22 ptr += 1;
23 assert(ptr[0] == 'c');
24 ptr += 1;
25 assert(ptr[0] == 'd');
26 ptr += 1;
27 assert(ptr[0] == 0);
28 ptr -= 1;
29 assert(ptr[0] == 'd');
30 ptr -= 1;
31 assert(ptr[0] == 'c');
32 ptr -= 1;
33 assert(ptr[0] == 'b');
34 ptr -= 1;
35 assert(ptr[0] == 'a');
36}
37
38test "double pointer parsing" {
39 comptime assert(PtrOf(PtrOf(i32)) == **i32);
40}
41
42fn PtrOf(comptime T: type) type {
43 return *T;
44}
test/cases/popcount.zig deleted-24
......@@ -1,24 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@popCount" {
4 comptime testPopCount();
5 testPopCount();
6}
7
8fn testPopCount() void {
9 {
10 var x: u32 = 0xaa;
11 assert(@popCount(x) == 4);
12 }
13 {
14 var x: u32 = 0xaaaaaaaa;
15 assert(@popCount(x) == 16);
16 }
17 {
18 var x: i16 = -1;
19 assert(@popCount(x) == 16);
20 }
21 comptime {
22 assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
23 }
24}
test/cases/ptrcast.zig deleted-52
......@@ -1,52 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "reinterpret bytes as integer with nonzero offset" {
6 testReinterpretBytesAsInteger();
7 comptime testReinterpretBytesAsInteger();
8}
9
10fn testReinterpretBytesAsInteger() void {
11 const bytes = "\x12\x34\x56\x78\xab";
12 const expected = switch (builtin.endian) {
13 builtin.Endian.Little => 0xab785634,
14 builtin.Endian.Big => 0x345678ab,
15 };
16 assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
17}
18
19test "reinterpret bytes of an array into an extern struct" {
20 testReinterpretBytesAsExternStruct();
21 comptime testReinterpretBytesAsExternStruct();
22}
23
24fn testReinterpretBytesAsExternStruct() void {
25 var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
26
27 const S = extern struct {
28 a: u8,
29 b: u16,
30 c: u8,
31 };
32
33 var ptr = @ptrCast(*const S, &bytes);
34 var val = ptr.c;
35 assertOrPanic(val == 5);
36}
37
38test "reinterpret struct field at comptime" {
39 const numLittle = comptime Bytes.init(0x12345678);
40 assertOrPanic(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes));
41}
42
43const Bytes = struct {
44 bytes: [4]u8,
45
46 pub fn init(v: u32) Bytes {
47 var res: Bytes = undefined;
48 @ptrCast(*align(1) u32, &res.bytes).* = v;
49
50 return res;
51 }
52};
test/cases/pub_enum/index.zig deleted-13
......@@ -1,13 +0,0 @@
1const other = @import("other.zig");
2const assert = @import("std").debug.assert;
3
4test "pub enum" {
5 pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) void {
8 assert(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 assert(other.size_t(42) == 42);
13}
test/cases/pub_enum/other.zig deleted-6
......@@ -1,6 +0,0 @@
1pub const APubEnum = enum {
2 One,
3 Two,
4 Three,
5};
6pub const size_t = u64;
test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig deleted-37
......@@ -1,37 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4var ok: bool = false;
5test "reference a variable in an if after an if in the 2nd switch prong" {
6 foo(true, Num.Two, false, "aoeu");
7 assert(!ok);
8 foo(false, Num.One, false, "aoeu");
9 assert(!ok);
10 foo(true, Num.One, false, "aoeu");
11 assert(ok);
12}
13
14const Num = enum {
15 One,
16 Two,
17};
18
19fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
20 switch (k) {
21 Num.Two => {},
22 Num.One => {
23 if (c) {
24 const output_path = b;
25
26 if (c2) {}
27
28 a(output_path);
29 }
30 },
31 }
32}
33
34fn a(x: []const u8) void {
35 assert(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/cases/reflection.zig deleted-95
......@@ -1,95 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: array, pointer, optional, error union type child" {
6 comptime {
7 assert(([10]u8).Child == u8);
8 assert((*u8).Child == u8);
9 assert((anyerror!u8).Payload == u8);
10 assert((?u8).Child == u8);
11 }
12}
13
14test "reflection: function return type, var args, and param types" {
15 comptime {
16 assert(@typeOf(dummy).ReturnType == i32);
17 assert(!@typeOf(dummy).is_var_args);
18 assert(@typeOf(dummy_varargs).is_var_args);
19 assert(@typeOf(dummy).arg_count == 3);
20 assert(@ArgType(@typeOf(dummy), 0) == bool);
21 assert(@ArgType(@typeOf(dummy), 1) == i32);
22 assert(@ArgType(@typeOf(dummy), 2) == f32);
23 }
24}
25
26fn dummy(a: bool, b: i32, c: f32) i32 {
27 return 1234;
28}
29fn dummy_varargs(args: ...) void {}
30
31test "reflection: struct member types and names" {
32 comptime {
33 assert(@memberCount(Foo) == 3);
34
35 assert(@memberType(Foo, 0) == i32);
36 assert(@memberType(Foo, 1) == bool);
37 assert(@memberType(Foo, 2) == void);
38
39 assert(mem.eql(u8, @memberName(Foo, 0), "one"));
40 assert(mem.eql(u8, @memberName(Foo, 1), "two"));
41 assert(mem.eql(u8, @memberName(Foo, 2), "three"));
42 }
43}
44
45test "reflection: enum member types and names" {
46 comptime {
47 assert(@memberCount(Bar) == 4);
48
49 assert(@memberType(Bar, 0) == void);
50 assert(@memberType(Bar, 1) == i32);
51 assert(@memberType(Bar, 2) == bool);
52 assert(@memberType(Bar, 3) == f64);
53
54 assert(mem.eql(u8, @memberName(Bar, 0), "One"));
55 assert(mem.eql(u8, @memberName(Bar, 1), "Two"));
56 assert(mem.eql(u8, @memberName(Bar, 2), "Three"));
57 assert(mem.eql(u8, @memberName(Bar, 3), "Four"));
58 }
59}
60
61test "reflection: @field" {
62 var f = Foo{
63 .one = 42,
64 .two = true,
65 .three = void{},
66 };
67
68 assert(f.one == f.one);
69 assert(@field(f, "o" ++ "ne") == f.one);
70 assert(@field(f, "t" ++ "wo") == f.two);
71 assert(@field(f, "th" ++ "ree") == f.three);
72 assert(@field(Foo, "const" ++ "ant") == Foo.constant);
73 assert(@field(Bar, "O" ++ "ne") == Bar.One);
74 assert(@field(Bar, "T" ++ "wo") == Bar.Two);
75 assert(@field(Bar, "Th" ++ "ree") == Bar.Three);
76 assert(@field(Bar, "F" ++ "our") == Bar.Four);
77 assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
78 @field(f, "o" ++ "ne") = 4;
79 assert(f.one == 4);
80}
81
82const Foo = struct {
83 const constant = 52;
84
85 one: i32,
86 two: bool,
87 three: void,
88};
89
90const Bar = union(enum) {
91 One: void,
92 Two: i32,
93 Three: bool,
94 Four: f64,
95};
test/cases/sizeof_and_typeof.zig deleted-69
......@@ -1,69 +0,0 @@
1const builtin = @import("builtin");
2const assert = @import("std").debug.assert;
3
4test "@sizeOf and @typeOf" {
5 const y: @typeOf(x) = 120;
6 assert(@sizeOf(@typeOf(y)) == 2);
7}
8const x: u16 = 13;
9const z: @typeOf(x) = 19;
10
11const A = struct {
12 a: u8,
13 b: u32,
14 c: u8,
15 d: u3,
16 e: u5,
17 f: u16,
18 g: u16,
19};
20
21const P = packed struct {
22 a: u8,
23 b: u32,
24 c: u8,
25 d: u3,
26 e: u5,
27 f: u16,
28 g: u16,
29};
30
31test "@byteOffsetOf" {
32 // Packed structs have fixed memory layout
33 assert(@byteOffsetOf(P, "a") == 0);
34 assert(@byteOffsetOf(P, "b") == 1);
35 assert(@byteOffsetOf(P, "c") == 5);
36 assert(@byteOffsetOf(P, "d") == 6);
37 assert(@byteOffsetOf(P, "e") == 6);
38 assert(@byteOffsetOf(P, "f") == 7);
39 assert(@byteOffsetOf(P, "g") == 9);
40
41 // Normal struct fields can be moved/padded
42 var a: A = undefined;
43 assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
44 assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
45 assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
46 assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
47 assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
48 assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
49 assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
50}
51
52test "@bitOffsetOf" {
53 // Packed structs have fixed memory layout
54 assert(@bitOffsetOf(P, "a") == 0);
55 assert(@bitOffsetOf(P, "b") == 8);
56 assert(@bitOffsetOf(P, "c") == 40);
57 assert(@bitOffsetOf(P, "d") == 48);
58 assert(@bitOffsetOf(P, "e") == 51);
59 assert(@bitOffsetOf(P, "f") == 56);
60 assert(@bitOffsetOf(P, "g") == 72);
61
62 assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
63 assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
64 assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
65 assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
66 assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
67 assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
68 assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
69}
test/cases/slice.zig deleted-40
......@@ -1,40 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4const x = @intToPtr([*]i32, 0x1000)[0..0x500];
5const y = x[0x100..];
6test "compile time slice of pointer to hard coded address" {
7 assert(@ptrToInt(x.ptr) == 0x1000);
8 assert(x.len == 0x500);
9
10 assert(@ptrToInt(y.ptr) == 0x1100);
11 assert(y.len == 0x400);
12}
13
14test "slice child property" {
15 var array: [5]i32 = undefined;
16 var slice = array[0..];
17 assert(@typeOf(slice).Child == i32);
18}
19
20test "runtime safety lets us slice from len..len" {
21 var an_array = []u8{
22 1,
23 2,
24 3,
25 };
26 assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
27}
28
29fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
30 return a_slice[start..end];
31}
32
33test "implicitly cast array of size 0 to slice" {
34 var msg = []u8{};
35 assertLenIsZero(msg);
36}
37
38fn assertLenIsZero(msg: []const u8) void {
39 assert(msg.len == 0);
40}
test/cases/struct.zig deleted-470
......@@ -1,470 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const StructWithNoFields = struct {
7 fn add(a: i32, b: i32) i32 {
8 return a + b;
9 }
10};
11const empty_global_instance = StructWithNoFields{};
12
13test "call struct static method" {
14 const result = StructWithNoFields.add(3, 4);
15 assert(result == 7);
16}
17
18test "return empty struct instance" {
19 _ = returnEmptyStructInstance();
20}
21fn returnEmptyStructInstance() StructWithNoFields {
22 return empty_global_instance;
23}
24
25const should_be_11 = StructWithNoFields.add(5, 6);
26
27test "invake static method in global scope" {
28 assert(should_be_11 == 11);
29}
30
31test "void struct fields" {
32 const foo = VoidStructFieldsFoo{
33 .a = void{},
34 .b = 1,
35 .c = void{},
36 };
37 assert(foo.b == 1);
38 assert(@sizeOf(VoidStructFieldsFoo) == 4);
39}
40const VoidStructFieldsFoo = struct {
41 a: void,
42 b: i32,
43 c: void,
44};
45
46test "structs" {
47 var foo: StructFoo = undefined;
48 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
49 foo.a += 1;
50 foo.b = foo.a == 1;
51 testFoo(foo);
52 testMutation(&foo);
53 assert(foo.c == 100);
54}
55const StructFoo = struct {
56 a: i32,
57 b: bool,
58 c: f32,
59};
60fn testFoo(foo: StructFoo) void {
61 assert(foo.b);
62}
63fn testMutation(foo: *StructFoo) void {
64 foo.c = 100;
65}
66
67const Node = struct {
68 val: Val,
69 next: *Node,
70};
71
72const Val = struct {
73 x: i32,
74};
75
76test "struct point to self" {
77 var root: Node = undefined;
78 root.val.x = 1;
79
80 var node: Node = undefined;
81 node.next = &root;
82 node.val.x = 2;
83
84 root.next = &node;
85
86 assert(node.next.next.next.val.x == 1);
87}
88
89test "struct byval assign" {
90 var foo1: StructFoo = undefined;
91 var foo2: StructFoo = undefined;
92
93 foo1.a = 1234;
94 foo2.a = 0;
95 assert(foo2.a == 0);
96 foo2 = foo1;
97 assert(foo2.a == 1234);
98}
99
100fn structInitializer() void {
101 const val = Val{ .x = 42 };
102 assert(val.x == 42);
103}
104
105test "fn call of struct field" {
106 assert(callStructField(Foo{ .ptr = aFunc }) == 13);
107}
108
109const Foo = struct {
110 ptr: fn () i32,
111};
112
113fn aFunc() i32 {
114 return 13;
115}
116
117fn callStructField(foo: Foo) i32 {
118 return foo.ptr();
119}
120
121test "store member function in variable" {
122 const instance = MemberFnTestFoo{ .x = 1234 };
123 const memberFn = MemberFnTestFoo.member;
124 const result = memberFn(instance);
125 assert(result == 1234);
126}
127const MemberFnTestFoo = struct {
128 x: i32,
129 fn member(foo: MemberFnTestFoo) i32 {
130 return foo.x;
131 }
132};
133
134test "call member function directly" {
135 const instance = MemberFnTestFoo{ .x = 1234 };
136 const result = MemberFnTestFoo.member(instance);
137 assert(result == 1234);
138}
139
140test "member functions" {
141 const r = MemberFnRand{ .seed = 1234 };
142 assert(r.getSeed() == 1234);
143}
144const MemberFnRand = struct {
145 seed: u32,
146 pub fn getSeed(r: *const MemberFnRand) u32 {
147 return r.seed;
148 }
149};
150
151test "return struct byval from function" {
152 const bar = makeBar(1234, 5678);
153 assert(bar.y == 5678);
154}
155const Bar = struct {
156 x: i32,
157 y: i32,
158};
159fn makeBar(x: i32, y: i32) Bar {
160 return Bar{
161 .x = x,
162 .y = y,
163 };
164}
165
166test "empty struct method call" {
167 const es = EmptyStruct{};
168 assert(es.method() == 1234);
169}
170const EmptyStruct = struct {
171 fn method(es: *const EmptyStruct) i32 {
172 return 1234;
173 }
174};
175
176test "return empty struct from fn" {
177 _ = testReturnEmptyStructFromFn();
178}
179const EmptyStruct2 = struct {};
180fn testReturnEmptyStructFromFn() EmptyStruct2 {
181 return EmptyStruct2{};
182}
183
184test "pass slice of empty struct to fn" {
185 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
186}
187fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
188 return slice.len;
189}
190
191const APackedStruct = packed struct {
192 x: u8,
193 y: u8,
194};
195
196test "packed struct" {
197 var foo = APackedStruct{
198 .x = 1,
199 .y = 2,
200 };
201 foo.y += 1;
202 const four = foo.x + foo.y;
203 assert(four == 4);
204}
205
206const BitField1 = packed struct {
207 a: u3,
208 b: u3,
209 c: u2,
210};
211
212const bit_field_1 = BitField1{
213 .a = 1,
214 .b = 2,
215 .c = 3,
216};
217
218test "bit field access" {
219 var data = bit_field_1;
220 assert(getA(&data) == 1);
221 assert(getB(&data) == 2);
222 assert(getC(&data) == 3);
223 comptime assert(@sizeOf(BitField1) == 1);
224
225 data.b += 1;
226 assert(data.b == 3);
227
228 data.a += 1;
229 assert(data.a == 2);
230 assert(data.b == 3);
231}
232
233fn getA(data: *const BitField1) u3 {
234 return data.a;
235}
236
237fn getB(data: *const BitField1) u3 {
238 return data.b;
239}
240
241fn getC(data: *const BitField1) u2 {
242 return data.c;
243}
244
245const Foo24Bits = packed struct {
246 field: u24,
247};
248const Foo96Bits = packed struct {
249 a: u24,
250 b: u24,
251 c: u24,
252 d: u24,
253};
254
255test "packed struct 24bits" {
256 comptime {
257 assert(@sizeOf(Foo24Bits) == 3);
258 assert(@sizeOf(Foo96Bits) == 12);
259 }
260
261 var value = Foo96Bits{
262 .a = 0,
263 .b = 0,
264 .c = 0,
265 .d = 0,
266 };
267 value.a += 1;
268 assert(value.a == 1);
269 assert(value.b == 0);
270 assert(value.c == 0);
271 assert(value.d == 0);
272
273 value.b += 1;
274 assert(value.a == 1);
275 assert(value.b == 1);
276 assert(value.c == 0);
277 assert(value.d == 0);
278
279 value.c += 1;
280 assert(value.a == 1);
281 assert(value.b == 1);
282 assert(value.c == 1);
283 assert(value.d == 0);
284
285 value.d += 1;
286 assert(value.a == 1);
287 assert(value.b == 1);
288 assert(value.c == 1);
289 assert(value.d == 1);
290}
291
292const FooArray24Bits = packed struct {
293 a: u16,
294 b: [2]Foo24Bits,
295 c: u16,
296};
297
298test "packed array 24bits" {
299 comptime {
300 assert(@sizeOf([9]Foo24Bits) == 9 * 3);
301 assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
302 }
303
304 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
305 bytes[bytes.len - 1] = 0xaa;
306 const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
307 assert(ptr.a == 0);
308 assert(ptr.b[0].field == 0);
309 assert(ptr.b[1].field == 0);
310 assert(ptr.c == 0);
311
312 ptr.a = maxInt(u16);
313 assert(ptr.a == maxInt(u16));
314 assert(ptr.b[0].field == 0);
315 assert(ptr.b[1].field == 0);
316 assert(ptr.c == 0);
317
318 ptr.b[0].field = maxInt(u24);
319 assert(ptr.a == maxInt(u16));
320 assert(ptr.b[0].field == maxInt(u24));
321 assert(ptr.b[1].field == 0);
322 assert(ptr.c == 0);
323
324 ptr.b[1].field = maxInt(u24);
325 assert(ptr.a == maxInt(u16));
326 assert(ptr.b[0].field == maxInt(u24));
327 assert(ptr.b[1].field == maxInt(u24));
328 assert(ptr.c == 0);
329
330 ptr.c = maxInt(u16);
331 assert(ptr.a == maxInt(u16));
332 assert(ptr.b[0].field == maxInt(u24));
333 assert(ptr.b[1].field == maxInt(u24));
334 assert(ptr.c == maxInt(u16));
335
336 assert(bytes[bytes.len - 1] == 0xaa);
337}
338
339const FooStructAligned = packed struct {
340 a: u8,
341 b: u8,
342};
343
344const FooArrayOfAligned = packed struct {
345 a: [2]FooStructAligned,
346};
347
348test "aligned array of packed struct" {
349 comptime {
350 assert(@sizeOf(FooStructAligned) == 2);
351 assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
352 }
353
354 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
355 const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
356
357 assert(ptr.a[0].a == 0xbb);
358 assert(ptr.a[0].b == 0xbb);
359 assert(ptr.a[1].a == 0xbb);
360 assert(ptr.a[1].b == 0xbb);
361}
362
363test "runtime struct initialization of bitfield" {
364 const s1 = Nibbles{
365 .x = x1,
366 .y = x1,
367 };
368 const s2 = Nibbles{
369 .x = @intCast(u4, x2),
370 .y = @intCast(u4, x2),
371 };
372
373 assert(s1.x == x1);
374 assert(s1.y == x1);
375 assert(s2.x == @intCast(u4, x2));
376 assert(s2.y == @intCast(u4, x2));
377}
378
379var x1 = u4(1);
380var x2 = u8(2);
381
382const Nibbles = packed struct {
383 x: u4,
384 y: u4,
385};
386
387const Bitfields = packed struct {
388 f1: u16,
389 f2: u16,
390 f3: u8,
391 f4: u8,
392 f5: u4,
393 f6: u4,
394 f7: u8,
395};
396
397test "native bit field understands endianness" {
398 var all: u64 = 0x7765443322221111;
399 var bytes: [8]u8 = undefined;
400 @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
401 var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
402
403 assert(bitfields.f1 == 0x1111);
404 assert(bitfields.f2 == 0x2222);
405 assert(bitfields.f3 == 0x33);
406 assert(bitfields.f4 == 0x44);
407 assert(bitfields.f5 == 0x5);
408 assert(bitfields.f6 == 0x6);
409 assert(bitfields.f7 == 0x77);
410}
411
412test "align 1 field before self referential align 8 field as slice return type" {
413 const result = alloc(Expr);
414 assert(result.len == 0);
415}
416
417const Expr = union(enum) {
418 Literal: u8,
419 Question: *Expr,
420};
421
422fn alloc(comptime T: type) []T {
423 return []T{};
424}
425
426test "call method with mutable reference to struct with no fields" {
427 const S = struct {
428 fn doC(s: *const @This()) bool {
429 return true;
430 }
431 fn do(s: *@This()) bool {
432 return true;
433 }
434 };
435
436 var s = S{};
437 assert(S.doC(&s));
438 assert(s.doC());
439 assert(S.do(&s));
440 assert(s.do());
441}
442
443test "implicit cast packed struct field to const ptr" {
444 const LevelUpMove = packed struct {
445 move_id: u9,
446 level: u7,
447
448 fn toInt(value: u7) u7 {
449 return value;
450 }
451 };
452
453 var lup: LevelUpMove = undefined;
454 lup.level = 12;
455 const res = LevelUpMove.toInt(lup.level);
456 assert(res == 12);
457}
458
459test "pointer to packed struct member in a stack variable" {
460 const S = packed struct {
461 a: u2,
462 b: u2,
463 };
464
465 var s = S{ .a = 2, .b = 0 };
466 var b_ptr = &s.b;
467 assert(s.b == 0);
468 b_ptr.* = 2;
469 assert(s.b == 2);
470}
test/cases/struct_contains_null_ptr_itself.zig deleted-21
......@@ -1,21 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 assert(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?*NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
test/cases/struct_contains_slice_of_itself.zig deleted-85
......@@ -1,85 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Node = struct {
4 payload: i32,
5 children: []Node,
6};
7
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
13test "struct contains slice of itself" {
14 var other_nodes = []Node{
15 Node{
16 .payload = 31,
17 .children = []Node{},
18 },
19 Node{
20 .payload = 32,
21 .children = []Node{},
22 },
23 };
24 var nodes = []Node{
25 Node{
26 .payload = 1,
27 .children = []Node{},
28 },
29 Node{
30 .payload = 2,
31 .children = []Node{},
32 },
33 Node{
34 .payload = 3,
35 .children = other_nodes[0..],
36 },
37 };
38 const root = Node{
39 .payload = 1234,
40 .children = nodes[0..],
41 };
42 assert(root.payload == 1234);
43 assert(root.children[0].payload == 1);
44 assert(root.children[1].payload == 2);
45 assert(root.children[2].payload == 3);
46 assert(root.children[2].children[0].payload == 31);
47 assert(root.children[2].children[1].payload == 32);
48}
49
50test "struct contains aligned slice of itself" {
51 var other_nodes = []NodeAligned{
52 NodeAligned{
53 .payload = 31,
54 .children = []NodeAligned{},
55 },
56 NodeAligned{
57 .payload = 32,
58 .children = []NodeAligned{},
59 },
60 };
61 var nodes = []NodeAligned{
62 NodeAligned{
63 .payload = 1,
64 .children = []NodeAligned{},
65 },
66 NodeAligned{
67 .payload = 2,
68 .children = []NodeAligned{},
69 },
70 NodeAligned{
71 .payload = 3,
72 .children = other_nodes[0..],
73 },
74 };
75 const root = NodeAligned{
76 .payload = 1234,
77 .children = nodes[0..],
78 };
79 assert(root.payload == 1234);
80 assert(root.children[0].payload == 1);
81 assert(root.children[1].payload == 2);
82 assert(root.children[2].payload == 3);
83 assert(root.children[2].children[0].payload == 31);
84 assert(root.children[2].children[1].payload == 32);
85}
test/cases/switch.zig deleted-271
......@@ -1,271 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "switch with numbers" {
4 testSwitchWithNumbers(13);
5}
6
7fn testSwitchWithNumbers(x: u32) void {
8 const result = switch (x) {
9 1, 2, 3, 4...8 => false,
10 13 => true,
11 else => false,
12 };
13 assert(result);
14}
15
16test "switch with all ranges" {
17 assert(testSwitchWithAllRanges(50, 3) == 1);
18 assert(testSwitchWithAllRanges(101, 0) == 2);
19 assert(testSwitchWithAllRanges(300, 5) == 3);
20 assert(testSwitchWithAllRanges(301, 6) == 6);
21}
22
23fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
24 return switch (x) {
25 0...100 => 1,
26 101...200 => 2,
27 201...300 => 3,
28 else => y,
29 };
30}
31
32test "implicit comptime switch" {
33 const x = 3 + 4;
34 const result = switch (x) {
35 3 => 10,
36 4 => 11,
37 5, 6 => 12,
38 7, 8 => 13,
39 else => 14,
40 };
41
42 comptime {
43 assert(result + 1 == 14);
44 }
45}
46
47test "switch on enum" {
48 const fruit = Fruit.Orange;
49 nonConstSwitchOnEnum(fruit);
50}
51const Fruit = enum {
52 Apple,
53 Orange,
54 Banana,
55};
56fn nonConstSwitchOnEnum(fruit: Fruit) void {
57 switch (fruit) {
58 Fruit.Apple => unreachable,
59 Fruit.Orange => {},
60 Fruit.Banana => unreachable,
61 }
62}
63
64test "switch statement" {
65 nonConstSwitch(SwitchStatmentFoo.C);
66}
67fn nonConstSwitch(foo: SwitchStatmentFoo) void {
68 const val = switch (foo) {
69 SwitchStatmentFoo.A => i32(1),
70 SwitchStatmentFoo.B => 2,
71 SwitchStatmentFoo.C => 3,
72 SwitchStatmentFoo.D => 4,
73 };
74 assert(val == 3);
75}
76const SwitchStatmentFoo = enum {
77 A,
78 B,
79 C,
80 D,
81};
82
83test "switch prong with variable" {
84 switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
85 switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
86 switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
87}
88const SwitchProngWithVarEnum = union(enum) {
89 One: i32,
90 Two: f32,
91 Meh: void,
92};
93fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void {
94 switch (a) {
95 SwitchProngWithVarEnum.One => |x| {
96 assert(x == 13);
97 },
98 SwitchProngWithVarEnum.Two => |x| {
99 assert(x == 13.0);
100 },
101 SwitchProngWithVarEnum.Meh => |x| {
102 const v: void = x;
103 },
104 }
105}
106
107test "switch on enum using pointer capture" {
108 testSwitchEnumPtrCapture();
109 comptime testSwitchEnumPtrCapture();
110}
111
112fn testSwitchEnumPtrCapture() void {
113 var value = SwitchProngWithVarEnum{ .One = 1234 };
114 switch (value) {
115 SwitchProngWithVarEnum.One => |*x| x.* += 1,
116 else => unreachable,
117 }
118 switch (value) {
119 SwitchProngWithVarEnum.One => |x| assert(x == 1235),
120 else => unreachable,
121 }
122}
123
124test "switch with multiple expressions" {
125 const x = switch (returnsFive()) {
126 1, 2, 3 => 1,
127 4, 5, 6 => 2,
128 else => i32(3),
129 };
130 assert(x == 2);
131}
132fn returnsFive() i32 {
133 return 5;
134}
135
136const Number = union(enum) {
137 One: u64,
138 Two: u8,
139 Three: f32,
140};
141
142const number = Number{ .Three = 1.23 };
143
144fn returnsFalse() bool {
145 switch (number) {
146 Number.One => |x| return x > 1234,
147 Number.Two => |x| return x == 'a',
148 Number.Three => |x| return x > 12.34,
149 }
150}
151test "switch on const enum with var" {
152 assert(!returnsFalse());
153}
154
155test "switch on type" {
156 assert(trueIfBoolFalseOtherwise(bool));
157 assert(!trueIfBoolFalseOtherwise(i32));
158}
159
160fn trueIfBoolFalseOtherwise(comptime T: type) bool {
161 return switch (T) {
162 bool => true,
163 else => false,
164 };
165}
166
167test "switch handles all cases of number" {
168 testSwitchHandleAllCases();
169 comptime testSwitchHandleAllCases();
170}
171
172fn testSwitchHandleAllCases() void {
173 assert(testSwitchHandleAllCasesExhaustive(0) == 3);
174 assert(testSwitchHandleAllCasesExhaustive(1) == 2);
175 assert(testSwitchHandleAllCasesExhaustive(2) == 1);
176 assert(testSwitchHandleAllCasesExhaustive(3) == 0);
177
178 assert(testSwitchHandleAllCasesRange(100) == 0);
179 assert(testSwitchHandleAllCasesRange(200) == 1);
180 assert(testSwitchHandleAllCasesRange(201) == 2);
181 assert(testSwitchHandleAllCasesRange(202) == 4);
182 assert(testSwitchHandleAllCasesRange(230) == 3);
183}
184
185fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
186 return switch (x) {
187 0 => u2(3),
188 1 => 2,
189 2 => 1,
190 3 => 0,
191 };
192}
193
194fn testSwitchHandleAllCasesRange(x: u8) u8 {
195 return switch (x) {
196 0...100 => u8(0),
197 101...200 => 1,
198 201, 203 => 2,
199 202 => 4,
200 204...255 => 3,
201 };
202}
203
204test "switch all prongs unreachable" {
205 testAllProngsUnreachable();
206 comptime testAllProngsUnreachable();
207}
208
209fn testAllProngsUnreachable() void {
210 assert(switchWithUnreachable(1) == 2);
211 assert(switchWithUnreachable(2) == 10);
212}
213
214fn switchWithUnreachable(x: i32) i32 {
215 while (true) {
216 switch (x) {
217 1 => return 2,
218 2 => break,
219 else => continue,
220 }
221 }
222 return 10;
223}
224
225fn return_a_number() anyerror!i32 {
226 return 1;
227}
228
229test "capture value of switch with all unreachable prongs" {
230 const x = return_a_number() catch |err| switch (err) {
231 else => unreachable,
232 };
233 assert(x == 1);
234}
235
236test "switching on booleans" {
237 testSwitchOnBools();
238 comptime testSwitchOnBools();
239}
240
241fn testSwitchOnBools() void {
242 assert(testSwitchOnBoolsTrueAndFalse(true) == false);
243 assert(testSwitchOnBoolsTrueAndFalse(false) == true);
244
245 assert(testSwitchOnBoolsTrueWithElse(true) == false);
246 assert(testSwitchOnBoolsTrueWithElse(false) == true);
247
248 assert(testSwitchOnBoolsFalseWithElse(true) == false);
249 assert(testSwitchOnBoolsFalseWithElse(false) == true);
250}
251
252fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
253 return switch (x) {
254 true => false,
255 false => true,
256 };
257}
258
259fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
260 return switch (x) {
261 true => false,
262 else => true,
263 };
264}
265
266fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
267 return switch (x) {
268 false => true,
269 else => false,
270 };
271}
test/cases/switch_prong_err_enum.zig deleted-30
......@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3var read_count: u64 = 0;
4
5fn readOnce() anyerror!u64 {
6 read_count += 1;
7 return read_count;
8}
9
10const FormValue = union(enum) {
11 Address: u64,
12 Other: bool,
13};
14
15fn doThing(form_id: u64) anyerror!FormValue {
16 return switch (form_id) {
17 17 => FormValue{ .Address = try readOnce() },
18 else => error.InvalidDebugInfo,
19 };
20}
21
22test "switch prong returns error enum" {
23 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| {
25 assert(payload == 1);
26 },
27 else => unreachable,
28 }
29 assert(read_count == 1);
30}
test/cases/switch_prong_implicit_cast.zig deleted-22
......@@ -1,22 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const FormValue = union(enum) {
4 One: void,
5 Two: bool,
6};
7
8fn foo(id: u64) !FormValue {
9 return switch (id) {
10 2 => FormValue{ .Two = true },
11 1 => FormValue{ .One = {} },
12 else => return error.Whatever,
13 };
14}
15
16test "switch prong implicit cast" {
17 const result = switch (foo(2) catch unreachable) {
18 FormValue.One => false,
19 FormValue.Two => |x| x,
20 };
21 assert(result);
22}
test/cases/syntax.zig deleted-59
......@@ -1,59 +0,0 @@
1// Test trailing comma syntax
2// zig fmt: off
3
4const struct_trailing_comma = struct { x: i32, y: i32, };
5const struct_no_comma = struct { x: i32, y: i32 };
6const struct_fn_no_comma = struct { fn m() void {} y: i32 };
7
8const enum_no_comma = enum { A, B };
9
10fn container_init() void {
11 const S = struct { x: i32, y: i32 };
12 _ = S { .x = 1, .y = 2 };
13 _ = S { .x = 1, .y = 2, };
14}
15
16fn type_expr_return1() if (true) A {}
17fn type_expr_return2() for (true) |_| A {}
18fn type_expr_return3() while (true) A {}
19fn type_expr_return4() comptime A {}
20
21fn switch_cases(x: i32) void {
22 switch (x) {
23 1,2,3 => {},
24 4,5, => {},
25 6...8, => {},
26 else => {},
27 }
28}
29
30fn switch_prongs(x: i32) void {
31 switch (x) {
32 0 => {},
33 else => {},
34 }
35 switch (x) {
36 0 => {},
37 else => {}
38 }
39}
40
41const fn_no_comma = fn(i32, i32)void;
42const fn_trailing_comma = fn(i32, i32,)void;
43
44fn fn_calls() void {
45 fn add(x: i32, y: i32,) i32 { x + y };
46 _ = add(1, 2);
47 _ = add(1, 2,);
48}
49
50fn asm_lists() void {
51 if (false) { // Build AST but don't analyze
52 asm ("not real assembly"
53 :[a] "x" (x),);
54 asm ("not real assembly"
55 :[a] "x" (->i32),:[a] "x" (1),);
56 asm ("still not real assembly"
57 :::"a","b",);
58 }
59}
test/cases/this.zig deleted-34
......@@ -1,34 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const module = @This();
4
5fn Point(comptime T: type) type {
6 return struct {
7 const Self = @This();
8 x: T,
9 y: T,
10
11 fn addOne(self: *Self) void {
12 self.x += 1;
13 self.y += 1;
14 }
15 };
16}
17
18fn add(x: i32, y: i32) i32 {
19 return x + y;
20}
21
22test "this refer to module call private fn" {
23 assert(module.add(1, 2) == 3);
24}
25
26test "this refer to container" {
27 var pt = Point(i32){
28 .x = 12,
29 .y = 34,
30 };
31 pt.addOne();
32 assert(pt.x == 13);
33 assert(pt.y == 35);
34}
test/cases/truncate.zig deleted-8
......@@ -1,8 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "truncate u0 to larger integer allowed and has comptime known result" {
5 var x: u0 = 0;
6 const y = @truncate(u8, x);
7 comptime assert(y == 0);
8}
test/cases/try.zig deleted-43
......@@ -1,43 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "try on error union" {
4 tryOnErrorUnionImpl();
5 comptime tryOnErrorUnionImpl();
6}
7
8fn tryOnErrorUnionImpl() void {
9 const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
10 error.ItBroke, error.NoMem => 1,
11 error.CrappedOut => i32(2),
12 else => unreachable,
13 };
14 assert(x == 11);
15}
16
17fn returnsTen() anyerror!i32 {
18 return 10;
19}
20
21test "try without vars" {
22 const result1 = if (failIfTrue(true)) 1 else |_| i32(2);
23 assert(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
26 assert(result2 == 1);
27}
28
29fn failIfTrue(ok: bool) anyerror!void {
30 if (ok) {
31 return error.ItBroke;
32 } else {
33 return;
34 }
35}
36
37test "try then not executed with assignment" {
38 if (failIfTrue(true)) {
39 unreachable;
40 } else |err| {
41 assert(err == error.ItBroke);
42 }
43}
test/cases/type_info.zig deleted-264
......@@ -1,264 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const TypeInfo = @import("builtin").TypeInfo;
4const TypeId = @import("builtin").TypeId;
5
6test "type info: tag type, void info" {
7 testBasic();
8 comptime testBasic();
9}
10
11fn testBasic() void {
12 assert(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 assert(TypeId(void_info) == TypeId.Void);
15 assert(void_info.Void == {});
16}
17
18test "type info: integer, floating point type info" {
19 testIntFloat();
20 comptime testIntFloat();
21}
22
23fn testIntFloat() void {
24 const u8_info = @typeInfo(u8);
25 assert(TypeId(u8_info) == TypeId.Int);
26 assert(!u8_info.Int.is_signed);
27 assert(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 assert(TypeId(f64_info) == TypeId.Float);
31 assert(f64_info.Float.bits == 64);
32}
33
34test "type info: pointer type info" {
35 testPointer();
36 comptime testPointer();
37}
38
39fn testPointer() void {
40 const u32_ptr_info = @typeInfo(*u32);
41 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
42 assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
43 assert(u32_ptr_info.Pointer.is_const == false);
44 assert(u32_ptr_info.Pointer.is_volatile == false);
45 assert(u32_ptr_info.Pointer.alignment == @alignOf(u32));
46 assert(u32_ptr_info.Pointer.child == u32);
47}
48
49test "type info: unknown length pointer type info" {
50 testUnknownLenPtr();
51 comptime testUnknownLenPtr();
52}
53
54fn testUnknownLenPtr() void {
55 const u32_ptr_info = @typeInfo([*]const volatile f64);
56 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
57 assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
58 assert(u32_ptr_info.Pointer.is_const == true);
59 assert(u32_ptr_info.Pointer.is_volatile == true);
60 assert(u32_ptr_info.Pointer.alignment == @alignOf(f64));
61 assert(u32_ptr_info.Pointer.child == f64);
62}
63
64test "type info: slice type info" {
65 testSlice();
66 comptime testSlice();
67}
68
69fn testSlice() void {
70 const u32_slice_info = @typeInfo([]u32);
71 assert(TypeId(u32_slice_info) == TypeId.Pointer);
72 assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
73 assert(u32_slice_info.Pointer.is_const == false);
74 assert(u32_slice_info.Pointer.is_volatile == false);
75 assert(u32_slice_info.Pointer.alignment == 4);
76 assert(u32_slice_info.Pointer.child == u32);
77}
78
79test "type info: array type info" {
80 testArray();
81 comptime testArray();
82}
83
84fn testArray() void {
85 const arr_info = @typeInfo([42]bool);
86 assert(TypeId(arr_info) == TypeId.Array);
87 assert(arr_info.Array.len == 42);
88 assert(arr_info.Array.child == bool);
89}
90
91test "type info: optional type info" {
92 testOptional();
93 comptime testOptional();
94}
95
96fn testOptional() void {
97 const null_info = @typeInfo(?void);
98 assert(TypeId(null_info) == TypeId.Optional);
99 assert(null_info.Optional.child == void);
100}
101
102test "type info: promise info" {
103 testPromise();
104 comptime testPromise();
105}
106
107fn testPromise() void {
108 const null_promise_info = @typeInfo(promise);
109 assert(TypeId(null_promise_info) == TypeId.Promise);
110 assert(null_promise_info.Promise.child == null);
111
112 const promise_info = @typeInfo(promise->usize);
113 assert(TypeId(promise_info) == TypeId.Promise);
114 assert(promise_info.Promise.child.? == usize);
115}
116
117test "type info: error set, error union info" {
118 testErrorSet();
119 comptime testErrorSet();
120}
121
122fn testErrorSet() void {
123 const TestErrorSet = error{
124 First,
125 Second,
126 Third,
127 };
128
129 const error_set_info = @typeInfo(TestErrorSet);
130 assert(TypeId(error_set_info) == TypeId.ErrorSet);
131 assert(error_set_info.ErrorSet.errors.len == 3);
132 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
133 assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
134
135 const error_union_info = @typeInfo(TestErrorSet!usize);
136 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
137 assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
138 assert(error_union_info.ErrorUnion.payload == usize);
139}
140
141test "type info: enum info" {
142 testEnum();
143 comptime testEnum();
144}
145
146fn testEnum() void {
147 const Os = enum {
148 Windows,
149 Macos,
150 Linux,
151 FreeBSD,
152 };
153
154 const os_info = @typeInfo(Os);
155 assert(TypeId(os_info) == TypeId.Enum);
156 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
157 assert(os_info.Enum.fields.len == 4);
158 assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
159 assert(os_info.Enum.fields[3].value == 3);
160 assert(os_info.Enum.tag_type == u2);
161 assert(os_info.Enum.defs.len == 0);
162}
163
164test "type info: union info" {
165 testUnion();
166 comptime testUnion();
167}
168
169fn testUnion() void {
170 const typeinfo_info = @typeInfo(TypeInfo);
171 assert(TypeId(typeinfo_info) == TypeId.Union);
172 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
173 assert(typeinfo_info.Union.tag_type.? == TypeId);
174 assert(typeinfo_info.Union.fields.len == 24);
175 assert(typeinfo_info.Union.fields[4].enum_field != null);
176 assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
177 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
178 assert(typeinfo_info.Union.defs.len == 20);
179
180 const TestNoTagUnion = union {
181 Foo: void,
182 Bar: u32,
183 };
184
185 const notag_union_info = @typeInfo(TestNoTagUnion);
186 assert(TypeId(notag_union_info) == TypeId.Union);
187 assert(notag_union_info.Union.tag_type == null);
188 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
189 assert(notag_union_info.Union.fields.len == 2);
190 assert(notag_union_info.Union.fields[0].enum_field == null);
191 assert(notag_union_info.Union.fields[1].field_type == u32);
192
193 const TestExternUnion = extern union {
194 foo: *c_void,
195 };
196
197 const extern_union_info = @typeInfo(TestExternUnion);
198 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
199 assert(extern_union_info.Union.tag_type == null);
200 assert(extern_union_info.Union.fields[0].enum_field == null);
201 assert(extern_union_info.Union.fields[0].field_type == *c_void);
202}
203
204test "type info: struct info" {
205 testStruct();
206 comptime testStruct();
207}
208
209fn testStruct() void {
210 const struct_info = @typeInfo(TestStruct);
211 assert(TypeId(struct_info) == TypeId.Struct);
212 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
213 assert(struct_info.Struct.fields.len == 3);
214 assert(struct_info.Struct.fields[1].offset == null);
215 assert(struct_info.Struct.fields[2].field_type == *TestStruct);
216 assert(struct_info.Struct.defs.len == 2);
217 assert(struct_info.Struct.defs[0].is_pub);
218 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
219 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
220 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
221 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
222}
223
224const TestStruct = packed struct {
225 const Self = @This();
226
227 fieldA: usize,
228 fieldB: void,
229 fieldC: *Self,
230
231 pub fn foo(self: *const Self) void {}
232};
233
234test "type info: function type info" {
235 testFunction();
236 comptime testFunction();
237}
238
239fn testFunction() void {
240 const fn_info = @typeInfo(@typeOf(foo));
241 assert(TypeId(fn_info) == TypeId.Fn);
242 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
243 assert(fn_info.Fn.is_generic);
244 assert(fn_info.Fn.args.len == 2);
245 assert(fn_info.Fn.is_var_args);
246 assert(fn_info.Fn.return_type == null);
247 assert(fn_info.Fn.async_allocator_type == null);
248
249 const test_instance: TestStruct = undefined;
250 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
251 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
252 assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
253}
254
255fn foo(comptime a: usize, b: bool, args: ...) usize {
256 return 0;
257}
258
259test "typeInfo with comptime parameter in struct fn def" {
260 const S = struct {
261 pub fn func(comptime x: f32) void {}
262 };
263 comptime var info = @typeInfo(S);
264}
test/cases/undefined.zig deleted-68
......@@ -1,68 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4fn initStaticArray() [10]i32 {
5 var array: [10]i32 = undefined;
6 array[0] = 1;
7 array[4] = 2;
8 array[7] = 3;
9 array[9] = 4;
10 return array;
11}
12const static_array = initStaticArray();
13test "init static array to undefined" {
14 assert(static_array[0] == 1);
15 assert(static_array[4] == 2);
16 assert(static_array[7] == 3);
17 assert(static_array[9] == 4);
18
19 comptime {
20 assert(static_array[0] == 1);
21 assert(static_array[4] == 2);
22 assert(static_array[7] == 3);
23 assert(static_array[9] == 4);
24 }
25}
26
27const Foo = struct {
28 x: i32,
29
30 fn setFooXMethod(foo: *Foo) void {
31 foo.x = 3;
32 }
33};
34
35fn setFooX(foo: *Foo) void {
36 foo.x = 2;
37}
38
39test "assign undefined to struct" {
40 comptime {
41 var foo: Foo = undefined;
42 setFooX(&foo);
43 assert(foo.x == 2);
44 }
45 {
46 var foo: Foo = undefined;
47 setFooX(&foo);
48 assert(foo.x == 2);
49 }
50}
51
52test "assign undefined to struct with method" {
53 comptime {
54 var foo: Foo = undefined;
55 foo.setFooXMethod();
56 assert(foo.x == 3);
57 }
58 {
59 var foo: Foo = undefined;
60 foo.setFooXMethod();
61 assert(foo.x == 3);
62 }
63}
64
65test "type name of undefined" {
66 const x = undefined;
67 assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
68}
test/cases/underscore.zig deleted-28
......@@ -1,28 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "ignore lval with underscore" {
5 _ = false;
6}
7
8test "ignore lval with underscore (for loop)" {
9 for ([]void{}) |_, i| {
10 for ([]void{}) |_, j| {
11 break;
12 }
13 break;
14 }
15}
16
17test "ignore lval with underscore (while loop)" {
18 while (optionalReturnError()) |_| {
19 while (optionalReturnError()) |_| {
20 break;
21 } else |_| {}
22 break;
23 } else |_| {}
24}
25
26fn optionalReturnError() !?u32 {
27 return error.optionalReturnError;
28}
test/cases/union.zig deleted-352
......@@ -1,352 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Value = union(enum) {
4 Int: u64,
5 Array: [9]u8,
6};
7
8const Agg = struct {
9 val1: Value,
10 val2: Value,
11};
12
13const v1 = Value{ .Int = 1234 };
14const v2 = Value{ .Array = []u8{3} ** 9 };
15
16const err = (anyerror!Agg)(Agg{
17 .val1 = v1,
18 .val2 = v2,
19});
20
21const array = []Value{
22 v1,
23 v2,
24 v1,
25 v2,
26};
27
28test "unions embedded in aggregate types" {
29 switch (array[1]) {
30 Value.Array => |arr| assert(arr[4] == 3),
31 else => unreachable,
32 }
33 switch ((err catch unreachable).val1) {
34 Value.Int => |x| assert(x == 1234),
35 else => unreachable,
36 }
37}
38
39const Foo = union {
40 float: f64,
41 int: i32,
42};
43
44test "basic unions" {
45 var foo = Foo{ .int = 1 };
46 assert(foo.int == 1);
47 foo = Foo{ .float = 12.34 };
48 assert(foo.float == 12.34);
49}
50
51test "comptime union field access" {
52 comptime {
53 var foo = Foo{ .int = 0 };
54 assert(foo.int == 0);
55
56 foo = Foo{ .float = 42.42 };
57 assert(foo.float == 42.42);
58 }
59}
60
61test "init union with runtime value" {
62 var foo: Foo = undefined;
63
64 setFloat(&foo, 12.34);
65 assert(foo.float == 12.34);
66
67 setInt(&foo, 42);
68 assert(foo.int == 42);
69}
70
71fn setFloat(foo: *Foo, x: f64) void {
72 foo.* = Foo{ .float = x };
73}
74
75fn setInt(foo: *Foo, x: i32) void {
76 foo.* = Foo{ .int = x };
77}
78
79const FooExtern = extern union {
80 float: f64,
81 int: i32,
82};
83
84test "basic extern unions" {
85 var foo = FooExtern{ .int = 1 };
86 assert(foo.int == 1);
87 foo.float = 12.34;
88 assert(foo.float == 12.34);
89}
90
91const Letter = enum {
92 A,
93 B,
94 C,
95};
96const Payload = union(Letter) {
97 A: i32,
98 B: f64,
99 C: bool,
100};
101
102test "union with specified enum tag" {
103 doTest();
104 comptime doTest();
105}
106
107fn doTest() void {
108 assert(bar(Payload{ .A = 1234 }) == -10);
109}
110
111fn bar(value: Payload) i32 {
112 assert(Letter(value) == Letter.A);
113 return switch (value) {
114 Payload.A => |x| return x - 1244,
115 Payload.B => |x| if (x == 12.34) i32(20) else 21,
116 Payload.C => |x| if (x) i32(30) else 31,
117 };
118}
119
120const MultipleChoice = union(enum(u32)) {
121 A = 20,
122 B = 40,
123 C = 60,
124 D = 1000,
125};
126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;
128 assert(x == MultipleChoice.C);
129 assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130}
131
132const MultipleChoice2 = union(enum(u32)) {
133 Unspecified1: i32,
134 A: f32 = 20,
135 Unspecified2: void,
136 B: bool = 40,
137 Unspecified3: i32,
138 C: i8 = 60,
139 Unspecified4: void,
140 D: void = 1000,
141 Unspecified5: i32,
142};
143
144test "union(enum(u32)) with specified and unspecified tag values" {
145 comptime assert(@TagType(@TagType(MultipleChoice2)) == u32);
146 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
147 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
148}
149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
151 assert(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
152 assert(1123 == switch (x) {
153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,
155 MultipleChoice2.C => |v| i32(1000) + v,
156 MultipleChoice2.D => 4,
157 MultipleChoice2.Unspecified1 => 5,
158 MultipleChoice2.Unspecified2 => 6,
159 MultipleChoice2.Unspecified3 => 7,
160 MultipleChoice2.Unspecified4 => 8,
161 MultipleChoice2.Unspecified5 => 9,
162 });
163}
164
165const ExternPtrOrInt = extern union {
166 ptr: *u8,
167 int: u64,
168};
169test "extern union size" {
170 comptime assert(@sizeOf(ExternPtrOrInt) == 8);
171}
172
173const PackedPtrOrInt = packed union {
174 ptr: *u8,
175 int: u64,
176};
177test "extern union size" {
178 comptime assert(@sizeOf(PackedPtrOrInt) == 8);
179}
180
181const ZeroBits = union {
182 OnlyField: void,
183};
184test "union with only 1 field which is void should be zero bits" {
185 comptime assert(@sizeOf(ZeroBits) == 0);
186}
187
188const TheTag = enum {
189 A,
190 B,
191 C,
192};
193const TheUnion = union(TheTag) {
194 A: i32,
195 B: i32,
196 C: i32,
197};
198test "union field access gives the enum values" {
199 assert(TheUnion.A == TheTag.A);
200 assert(TheUnion.B == TheTag.B);
201 assert(TheUnion.C == TheTag.C);
202}
203
204test "cast union to tag type of union" {
205 testCastUnionToTagType(TheUnion{ .B = 1234 });
206 comptime testCastUnionToTagType(TheUnion{ .B = 1234 });
207}
208
209fn testCastUnionToTagType(x: TheUnion) void {
210 assert(TheTag(x) == TheTag.B);
211}
212
213test "cast tag type of union to union" {
214 var x: Value2 = Letter2.B;
215 assert(Letter2(x) == Letter2.B);
216}
217const Letter2 = enum {
218 A,
219 B,
220 C,
221};
222const Value2 = union(Letter2) {
223 A: i32,
224 B,
225 C,
226};
227
228test "implicit cast union to its tag type" {
229 var x: Value2 = Letter2.B;
230 assert(x == Letter2.B);
231 giveMeLetterB(x);
232}
233fn giveMeLetterB(x: Letter2) void {
234 assert(x == Value2.B);
235}
236
237pub const PackThis = union(enum) {
238 Invalid: bool,
239 StringLiteral: u2,
240};
241
242test "constant packed union" {
243 testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }});
244}
245
246fn testConstPackedUnion(expected_tokens: []const PackThis) void {
247 assert(expected_tokens[0].StringLiteral == 1);
248}
249
250test "switch on union with only 1 field" {
251 var r: PartialInst = undefined;
252 r = PartialInst.Compiled;
253 switch (r) {
254 PartialInst.Compiled => {
255 var z: PartialInstWithPayload = undefined;
256 z = PartialInstWithPayload{ .Compiled = 1234 };
257 switch (z) {
258 PartialInstWithPayload.Compiled => |x| {
259 assert(x == 1234);
260 return;
261 },
262 }
263 },
264 }
265 unreachable;
266}
267
268const PartialInst = union(enum) {
269 Compiled,
270};
271
272const PartialInstWithPayload = union(enum) {
273 Compiled: i32,
274};
275
276test "access a member of tagged union with conflicting enum tag name" {
277 const Bar = union(enum) {
278 A: A,
279 B: B,
280
281 const A = u8;
282 const B = void;
283 };
284
285 comptime assert(Bar.A == u8);
286}
287
288test "tagged union initialization with runtime void" {
289 assert(testTaggedUnionInit({}));
290}
291
292const TaggedUnionWithAVoid = union(enum) {
293 A,
294 B: i32,
295};
296
297fn testTaggedUnionInit(x: var) bool {
298 const y = TaggedUnionWithAVoid{ .A = x };
299 return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A;
300}
301
302pub const UnionEnumNoPayloads = union(enum) {
303 A,
304 B,
305};
306
307test "tagged union with no payloads" {
308 const a = UnionEnumNoPayloads{ .B = {} };
309 switch (a) {
310 @TagType(UnionEnumNoPayloads).A => @panic("wrong"),
311 @TagType(UnionEnumNoPayloads).B => {},
312 }
313}
314
315test "union with only 1 field casted to its enum type" {
316 const Literal = union(enum) {
317 Number: f64,
318 Bool: bool,
319 };
320
321 const Expr = union(enum) {
322 Literal: Literal,
323 };
324
325 var e = Expr{ .Literal = Literal{ .Bool = true } };
326 const Tag = @TagType(Expr);
327 comptime assert(@TagType(Tag) == comptime_int);
328 var t = Tag(e);
329 assert(t == Expr.Literal);
330}
331
332test "union with only 1 field casted to its enum type which has enum value specified" {
333 const Literal = union(enum) {
334 Number: f64,
335 Bool: bool,
336 };
337
338 const Tag = enum {
339 Literal = 33,
340 };
341
342 const Expr = union(Tag) {
343 Literal: Literal,
344 };
345
346 var e = Expr{ .Literal = Literal{ .Bool = true } };
347 comptime assert(@TagType(Tag) == comptime_int);
348 var t = Tag(e);
349 assert(t == Expr.Literal);
350 assert(@enumToInt(t) == 33);
351 comptime assert(@enumToInt(t) == 33);
352}
test/cases/var_args.zig deleted-84
......@@ -1,84 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn add(args: ...) i32 {
4 var sum = i32(0);
5 {
6 comptime var i: usize = 0;
7 inline while (i < args.len) : (i += 1) {
8 sum += args[i];
9 }
10 }
11 return sum;
12}
13
14test "add arbitrary args" {
15 assert(add(i32(1), i32(2), i32(3), i32(4)) == 10);
16 assert(add(i32(1234)) == 1234);
17 assert(add() == 0);
18}
19
20fn readFirstVarArg(args: ...) void {
21 const value = args[0];
22}
23
24test "send void arg to var args" {
25 readFirstVarArg({});
26}
27
28test "pass args directly" {
29 assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
30 assert(addSomeStuff(i32(1234)) == 1234);
31 assert(addSomeStuff() == 0);
32}
33
34fn addSomeStuff(args: ...) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 assert(extraFn(10) == 0);
40 assert(extraFn(10, false) == 1);
41 assert(extraFn(10, false, true) == 2);
42
43 // TODO issue #313
44 //comptime {
45 // assert(extraFn(10) == 0);
46 // assert(extraFn(10, false) == 1);
47 // assert(extraFn(10, false, true) == 2);
48 //}
49}
50
51fn extraFn(extra: u32, args: ...) usize {
52 if (args.len >= 1) {
53 assert(args[0] == false);
54 }
55 if (args.len >= 2) {
56 assert(args[1] == true);
57 }
58 return args.len;
59}
60
61const foos = []fn (...) bool{
62 foo1,
63 foo2,
64};
65
66fn foo1(args: ...) bool {
67 return true;
68}
69fn foo2(args: ...) bool {
70 return false;
71}
72
73test "array of var args functions" {
74 assert(foos[0]());
75 assert(!foos[1]());
76}
77
78test "pass zero length array to var args param" {
79 doNothingWithFirstArg("");
80}
81
82fn doNothingWithFirstArg(args: ...) void {
83 const a = args[0];
84}
test/cases/void.zig deleted-30
......@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9test "compare void with void compile time known" {
10 comptime {
11 const foo = Foo{
12 .a = {},
13 .b = 1,
14 .c = {},
15 };
16 assert(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 assert(i == j);
24 j += 1;
25 }
26}
27
28fn times(n: usize) []const void {
29 return ([*]void)(undefined)[0..n];
30}
test/cases/while.zig deleted-227
......@@ -1,227 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "while loop" {
4 var i: i32 = 0;
5 while (i < 4) {
6 i += 1;
7 }
8 assert(i == 4);
9 assert(whileLoop1() == 1);
10}
11fn whileLoop1() i32 {
12 return whileLoop2();
13}
14fn whileLoop2() i32 {
15 while (true) {
16 return 1;
17 }
18}
19test "static eval while" {
20 assert(static_eval_while_number == 1);
21}
22const static_eval_while_number = staticWhileLoop1();
23fn staticWhileLoop1() i32 {
24 return whileLoop2();
25}
26fn staticWhileLoop2() i32 {
27 while (true) {
28 return 1;
29 }
30}
31
32test "continue and break" {
33 runContinueAndBreakTest();
34 assert(continue_and_break_counter == 8);
35}
36var continue_and_break_counter: i32 = 0;
37fn runContinueAndBreakTest() void {
38 var i: i32 = 0;
39 while (true) {
40 continue_and_break_counter += 2;
41 i += 1;
42 if (i < 4) {
43 continue;
44 }
45 break;
46 }
47 assert(i == 4);
48}
49
50test "return with implicit cast from while loop" {
51 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
52}
53fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
54 while (true) {
55 return;
56 }
57}
58
59test "while with continue expression" {
60 var sum: i32 = 0;
61 {
62 var i: i32 = 0;
63 while (i < 10) : (i += 1) {
64 if (i == 5) continue;
65 sum += i;
66 }
67 }
68 assert(sum == 40);
69}
70
71test "while with else" {
72 var sum: i32 = 0;
73 var i: i32 = 0;
74 var got_else: i32 = 0;
75 while (i < 10) : (i += 1) {
76 sum += 1;
77 } else {
78 got_else += 1;
79 }
80 assert(sum == 10);
81 assert(got_else == 1);
82}
83
84test "while with optional as condition" {
85 numbers_left = 10;
86 var sum: i32 = 0;
87 while (getNumberOrNull()) |value| {
88 sum += value;
89 }
90 assert(sum == 45);
91}
92
93test "while with optional as condition with else" {
94 numbers_left = 10;
95 var sum: i32 = 0;
96 var got_else: i32 = 0;
97 while (getNumberOrNull()) |value| {
98 sum += value;
99 assert(got_else == 0);
100 } else {
101 got_else += 1;
102 }
103 assert(sum == 45);
104 assert(got_else == 1);
105}
106
107test "while with error union condition" {
108 numbers_left = 10;
109 var sum: i32 = 0;
110 var got_else: i32 = 0;
111 while (getNumberOrErr()) |value| {
112 sum += value;
113 } else |err| {
114 assert(err == error.OutOfNumbers);
115 got_else += 1;
116 }
117 assert(sum == 45);
118 assert(got_else == 1);
119}
120
121var numbers_left: i32 = undefined;
122fn getNumberOrErr() anyerror!i32 {
123 return if (numbers_left == 0) error.OutOfNumbers else x: {
124 numbers_left -= 1;
125 break :x numbers_left;
126 };
127}
128fn getNumberOrNull() ?i32 {
129 return if (numbers_left == 0) null else x: {
130 numbers_left -= 1;
131 break :x numbers_left;
132 };
133}
134
135test "while on optional with else result follow else prong" {
136 const result = while (returnNull()) |value| {
137 break value;
138 } else
139 i32(2);
140 assert(result == 2);
141}
142
143test "while on optional with else result follow break prong" {
144 const result = while (returnOptional(10)) |value| {
145 break value;
146 } else
147 i32(2);
148 assert(result == 10);
149}
150
151test "while on error union with else result follow else prong" {
152 const result = while (returnError()) |value| {
153 break value;
154 } else |err|
155 i32(2);
156 assert(result == 2);
157}
158
159test "while on error union with else result follow break prong" {
160 const result = while (returnSuccess(10)) |value| {
161 break value;
162 } else |err|
163 i32(2);
164 assert(result == 10);
165}
166
167test "while on bool with else result follow else prong" {
168 const result = while (returnFalse()) {
169 break i32(10);
170 } else
171 i32(2);
172 assert(result == 2);
173}
174
175test "while on bool with else result follow break prong" {
176 const result = while (returnTrue()) {
177 break i32(10);
178 } else
179 i32(2);
180 assert(result == 10);
181}
182
183test "break from outer while loop" {
184 testBreakOuter();
185 comptime testBreakOuter();
186}
187
188fn testBreakOuter() void {
189 outer: while (true) {
190 while (true) {
191 break :outer;
192 }
193 }
194}
195
196test "continue outer while loop" {
197 testContinueOuter();
198 comptime testContinueOuter();
199}
200
201fn testContinueOuter() void {
202 var i: usize = 0;
203 outer: while (i < 10) : (i += 1) {
204 while (true) {
205 continue :outer;
206 }
207 }
208}
209
210fn returnNull() ?i32 {
211 return null;
212}
213fn returnOptional(x: i32) ?i32 {
214 return x;
215}
216fn returnError() anyerror!i32 {
217 return error.YouWantedAnError;
218}
219fn returnSuccess(x: i32) anyerror!i32 {
220 return x;
221}
222fn returnFalse() bool {
223 return false;
224}
225fn returnTrue() bool {
226 return true;
227}
test/cases/widening.zig deleted-27
......@@ -1,27 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4
5test "integer widening" {
6 var a: u8 = 250;
7 var b: u16 = a;
8 var c: u32 = b;
9 var d: u64 = c;
10 var e: u64 = d;
11 var f: u128 = e;
12 assert(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 assert(b == 250);
19}
20
21test "float widening" {
22 var a: f16 = 12.34;
23 var b: f32 = a;
24 var c: f64 = b;
25 var d: f128 = c;
26 assert(d == a);
27}
test/compile_errors.zig+2-2
......@@ -3220,7 +3220,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
32203220 \\ return 2;
32213221 \\}
32223222 ,
3223 ".tmp_source.zig:2:15: error: unable to infer expression type",
3223 ".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known",
32243224 );
32253225
32263226 cases.add(
......@@ -3566,7 +3566,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
35663566 \\
35673567 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
35683568 ,
3569 ".tmp_source.zig:2:11: error: expected type, found 'i32'",
3569 ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'",
35703570 );
35713571
35723572 cases.add(
test/stage1/behavior.zig created+80
......@@ -0,0 +1,80 @@
1comptime {
2 _ = @import("behavior/align.zig");
3 _ = @import("behavior/alignof.zig");
4 _ = @import("behavior/array.zig");
5 _ = @import("behavior/asm.zig");
6 _ = @import("behavior/atomics.zig");
7 _ = @import("behavior/bit_shifting.zig");
8 _ = @import("behavior/bitcast.zig");
9 _ = @import("behavior/bitreverse.zig");
10 _ = @import("behavior/bool.zig");
11 _ = @import("behavior/bswap.zig");
12 _ = @import("behavior/bugs/1076.zig");
13 _ = @import("behavior/bugs/1111.zig");
14 _ = @import("behavior/bugs/1277.zig");
15 _ = @import("behavior/bugs/1322.zig");
16 _ = @import("behavior/bugs/1381.zig");
17 _ = @import("behavior/bugs/1421.zig");
18 _ = @import("behavior/bugs/1442.zig");
19 _ = @import("behavior/bugs/1486.zig");
20 _ = @import("behavior/bugs/394.zig");
21 _ = @import("behavior/bugs/655.zig");
22 _ = @import("behavior/bugs/656.zig");
23 _ = @import("behavior/bugs/726.zig");
24 _ = @import("behavior/bugs/828.zig");
25 _ = @import("behavior/bugs/920.zig");
26 _ = @import("behavior/byval_arg_var.zig");
27 _ = @import("behavior/cancel.zig");
28 _ = @import("behavior/cast.zig");
29 _ = @import("behavior/const_slice_child.zig");
30 _ = @import("behavior/coroutine_await_struct.zig");
31 _ = @import("behavior/coroutines.zig");
32 _ = @import("behavior/defer.zig");
33 _ = @import("behavior/enum.zig");
34 _ = @import("behavior/enum_with_members.zig");
35 _ = @import("behavior/error.zig");
36 _ = @import("behavior/eval.zig");
37 _ = @import("behavior/field_parent_ptr.zig");
38 _ = @import("behavior/fn.zig");
39 _ = @import("behavior/fn_in_struct_in_comptime.zig");
40 _ = @import("behavior/for.zig");
41 _ = @import("behavior/generics.zig");
42 _ = @import("behavior/if.zig");
43 _ = @import("behavior/import.zig");
44 _ = @import("behavior/incomplete_struct_param_tld.zig");
45 _ = @import("behavior/inttoptr.zig");
46 _ = @import("behavior/ir_block_deps.zig");
47 _ = @import("behavior/math.zig");
48 _ = @import("behavior/merge_error_sets.zig");
49 _ = @import("behavior/misc.zig");
50 _ = @import("behavior/namespace_depends_on_compile_var/index.zig");
51 _ = @import("behavior/new_stack_call.zig");
52 _ = @import("behavior/null.zig");
53 _ = @import("behavior/optional.zig");
54 _ = @import("behavior/pointers.zig");
55 _ = @import("behavior/popcount.zig");
56 _ = @import("behavior/ptrcast.zig");
57 _ = @import("behavior/pub_enum/index.zig");
58 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
59 _ = @import("behavior/reflection.zig");
60 _ = @import("behavior/sizeof_and_typeof.zig");
61 _ = @import("behavior/slice.zig");
62 _ = @import("behavior/struct.zig");
63 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
64 _ = @import("behavior/struct_contains_slice_of_itself.zig");
65 _ = @import("behavior/switch.zig");
66 _ = @import("behavior/switch_prong_err_enum.zig");
67 _ = @import("behavior/switch_prong_implicit_cast.zig");
68 _ = @import("behavior/syntax.zig");
69 _ = @import("behavior/this.zig");
70 _ = @import("behavior/truncate.zig");
71 _ = @import("behavior/try.zig");
72 _ = @import("behavior/type_info.zig");
73 _ = @import("behavior/undefined.zig");
74 _ = @import("behavior/underscore.zig");
75 _ = @import("behavior/union.zig");
76 _ = @import("behavior/var_args.zig");
77 _ = @import("behavior/void.zig");
78 _ = @import("behavior/while.zig");
79 _ = @import("behavior/widening.zig");
80}
test/stage1/behavior/align.zig created+230
......@@ -0,0 +1,230 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const builtin = @import("builtin");
3
4var foo: u8 align(4) = 100;
5
6test "global variable alignment" {
7 assertOrPanic(@typeOf(&foo).alignment == 4);
8 assertOrPanic(@typeOf(&foo) == *align(4) u8);
9 const slice = (*[1]u8)(&foo)[0..];
10 assertOrPanic(@typeOf(slice) == []align(4) u8);
11}
12
13fn derp() align(@sizeOf(usize) * 2) i32 {
14 return 1234;
15}
16fn noop1() align(1) void {}
17fn noop4() align(4) void {}
18
19test "function alignment" {
20 assertOrPanic(derp() == 1234);
21 assertOrPanic(@typeOf(noop1) == fn () align(1) void);
22 assertOrPanic(@typeOf(noop4) == fn () align(4) void);
23 noop1();
24 noop4();
25}
26
27var baz: packed struct {
28 a: u32,
29 b: u32,
30} = undefined;
31
32test "packed struct alignment" {
33 assertOrPanic(@typeOf(&baz.b) == *align(1) u32);
34}
35
36const blah: packed struct {
37 a: u3,
38 b: u3,
39 c: u2,
40} = undefined;
41
42test "bit field alignment" {
43 assertOrPanic(@typeOf(&blah.b) == *align(1:3:1) const u3);
44}
45
46test "default alignment allows unspecified in type syntax" {
47 assertOrPanic(*u32 == *align(@alignOf(u32)) u32);
48}
49
50test "implicitly decreasing pointer alignment" {
51 const a: u32 align(4) = 3;
52 const b: u32 align(8) = 4;
53 assertOrPanic(addUnaligned(&a, &b) == 7);
54}
55
56fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
57 return a.* + b.*;
58}
59
60test "implicitly decreasing slice alignment" {
61 const a: u32 align(4) = 3;
62 const b: u32 align(8) = 4;
63 assertOrPanic(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
64}
65fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
66 return a[0] + b[0];
67}
68
69test "specifying alignment allows pointer cast" {
70 testBytesAlign(0x33);
71}
72fn testBytesAlign(b: u8) void {
73 var bytes align(4) = []u8{
74 b,
75 b,
76 b,
77 b,
78 };
79 const ptr = @ptrCast(*u32, &bytes[0]);
80 assertOrPanic(ptr.* == 0x33333333);
81}
82
83test "specifying alignment allows slice cast" {
84 testBytesAlignSlice(0x33);
85}
86fn testBytesAlignSlice(b: u8) void {
87 var bytes align(4) = []u8{
88 b,
89 b,
90 b,
91 b,
92 };
93 const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
94 assertOrPanic(slice[0] == 0x33333333);
95}
96
97test "@alignCast pointers" {
98 var x: u32 align(4) = 1;
99 expectsOnly1(&x);
100 assertOrPanic(x == 2);
101}
102fn expectsOnly1(x: *align(1) u32) void {
103 expects4(@alignCast(4, x));
104}
105fn expects4(x: *align(4) u32) void {
106 x.* += 1;
107}
108
109test "@alignCast slices" {
110 var array align(4) = []u32{
111 1,
112 1,
113 };
114 const slice = array[0..];
115 sliceExpectsOnly1(slice);
116 assertOrPanic(slice[0] == 2);
117}
118fn sliceExpectsOnly1(slice: []align(1) u32) void {
119 sliceExpects4(@alignCast(4, slice));
120}
121fn sliceExpects4(slice: []align(4) u32) void {
122 slice[0] += 1;
123}
124
125test "implicitly decreasing fn alignment" {
126 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
127 testImplicitlyDecreaseFnAlign(alignedBig, 5678);
128}
129
130fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
131 assertOrPanic(ptr() == answer);
132}
133
134fn alignedSmall() align(8) i32 {
135 return 1234;
136}
137fn alignedBig() align(16) i32 {
138 return 5678;
139}
140
141test "@alignCast functions" {
142 assertOrPanic(fnExpectsOnly1(simple4) == 0x19);
143}
144fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
145 return fnExpects4(@alignCast(4, ptr));
146}
147fn fnExpects4(ptr: fn () align(4) i32) i32 {
148 return ptr();
149}
150fn simple4() align(4) i32 {
151 return 0x19;
152}
153
154test "generic function with align param" {
155 assertOrPanic(whyWouldYouEverDoThis(1) == 0x1);
156 assertOrPanic(whyWouldYouEverDoThis(4) == 0x1);
157 assertOrPanic(whyWouldYouEverDoThis(8) == 0x1);
158}
159
160fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
161 return 0x1;
162}
163
164test "@ptrCast preserves alignment of bigger source" {
165 var x: u32 align(16) = 1234;
166 const ptr = @ptrCast(*u8, &x);
167 assertOrPanic(@typeOf(ptr) == *align(16) u8);
168}
169
170test "runtime known array index has best alignment possible" {
171 // take full advantage of over-alignment
172 var array align(4) = []u8{ 1, 2, 3, 4 };
173 assertOrPanic(@typeOf(&array[0]) == *align(4) u8);
174 assertOrPanic(@typeOf(&array[1]) == *u8);
175 assertOrPanic(@typeOf(&array[2]) == *align(2) u8);
176 assertOrPanic(@typeOf(&array[3]) == *u8);
177
178 // because align is too small but we still figure out to use 2
179 var bigger align(2) = []u64{ 1, 2, 3, 4 };
180 assertOrPanic(@typeOf(&bigger[0]) == *align(2) u64);
181 assertOrPanic(@typeOf(&bigger[1]) == *align(2) u64);
182 assertOrPanic(@typeOf(&bigger[2]) == *align(2) u64);
183 assertOrPanic(@typeOf(&bigger[3]) == *align(2) u64);
184
185 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
186 var smaller align(2) = []u32{ 1, 2, 3, 4 };
187 comptime assertOrPanic(@typeOf(smaller[0..]) == []align(2) u32);
188 comptime assertOrPanic(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
189 testIndex(smaller[0..].ptr, 0, *align(2) u32);
190 testIndex(smaller[0..].ptr, 1, *align(2) u32);
191 testIndex(smaller[0..].ptr, 2, *align(2) u32);
192 testIndex(smaller[0..].ptr, 3, *align(2) u32);
193
194 // has to use ABI alignment because index known at runtime only
195 testIndex2(array[0..].ptr, 0, *u8);
196 testIndex2(array[0..].ptr, 1, *u8);
197 testIndex2(array[0..].ptr, 2, *u8);
198 testIndex2(array[0..].ptr, 3, *u8);
199}
200fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
201 comptime assertOrPanic(@typeOf(&smaller[index]) == T);
202}
203fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
204 comptime assertOrPanic(@typeOf(&ptr[index]) == T);
205}
206
207test "alignstack" {
208 assertOrPanic(fnWithAlignedStack() == 1234);
209}
210
211fn fnWithAlignedStack() i32 {
212 @setAlignStack(256);
213 return 1234;
214}
215
216test "alignment of structs" {
217 assertOrPanic(@alignOf(struct {
218 a: i32,
219 b: *i32,
220 }) == @alignOf(usize));
221}
222
223test "alignment of extern() void" {
224 var runtime_nothing = nothing;
225 const casted1 = @ptrCast(*const u8, runtime_nothing);
226 const casted2 = @ptrCast(extern fn () void, casted1);
227 casted2();
228}
229
230extern fn nothing() void {}
test/stage1/behavior/alignof.zig created+18
......@@ -0,0 +1,18 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const Foo = struct {
7 x: u32,
8 y: u32,
9 z: u32,
10};
11
12test "@alignOf(T) before referencing T" {
13 comptime assertOrPanic(@alignOf(Foo) != maxInt(usize));
14 if (builtin.arch == builtin.Arch.x86_64) {
15 comptime assertOrPanic(@alignOf(Foo) == 4);
16 }
17}
18
test/stage1/behavior/array.zig created+270
......@@ -0,0 +1,270 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4test "arrays" {
5 var array: [5]u32 = undefined;
6
7 var i: u32 = 0;
8 while (i < 5) {
9 array[i] = i + 1;
10 i = array[i];
11 }
12
13 i = 0;
14 var accumulator = u32(0);
15 while (i < 5) {
16 accumulator += array[i];
17
18 i += 1;
19 }
20
21 assertOrPanic(accumulator == 15);
22 assertOrPanic(getArrayLen(array) == 5);
23}
24fn getArrayLen(a: []const u32) usize {
25 return a.len;
26}
27
28test "void arrays" {
29 var array: [4]void = undefined;
30 array[0] = void{};
31 array[1] = array[2];
32 assertOrPanic(@sizeOf(@typeOf(array)) == 0);
33 assertOrPanic(array.len == 4);
34}
35
36test "array literal" {
37 const hex_mult = []u16{
38 4096,
39 256,
40 16,
41 1,
42 };
43
44 assertOrPanic(hex_mult.len == 4);
45 assertOrPanic(hex_mult[1] == 256);
46}
47
48test "array dot len const expr" {
49 assertOrPanic(comptime x: {
50 break :x some_array.len == 4;
51 });
52}
53
54const ArrayDotLenConstExpr = struct {
55 y: [some_array.len]u8,
56};
57const some_array = []u8{
58 0,
59 1,
60 2,
61 3,
62};
63
64test "nested arrays" {
65 const array_of_strings = [][]const u8{
66 "hello",
67 "this",
68 "is",
69 "my",
70 "thing",
71 };
72 for (array_of_strings) |s, i| {
73 if (i == 0) assertOrPanic(mem.eql(u8, s, "hello"));
74 if (i == 1) assertOrPanic(mem.eql(u8, s, "this"));
75 if (i == 2) assertOrPanic(mem.eql(u8, s, "is"));
76 if (i == 3) assertOrPanic(mem.eql(u8, s, "my"));
77 if (i == 4) assertOrPanic(mem.eql(u8, s, "thing"));
78 }
79}
80
81var s_array: [8]Sub = undefined;
82const Sub = struct {
83 b: u8,
84};
85const Str = struct {
86 a: []Sub,
87};
88test "set global var array via slice embedded in struct" {
89 var s = Str{ .a = s_array[0..] };
90
91 s.a[0].b = 1;
92 s.a[1].b = 2;
93 s.a[2].b = 3;
94
95 assertOrPanic(s_array[0].b == 1);
96 assertOrPanic(s_array[1].b == 2);
97 assertOrPanic(s_array[2].b == 3);
98}
99
100test "array literal with specified size" {
101 var array = [2]u8{
102 1,
103 2,
104 };
105 assertOrPanic(array[0] == 1);
106 assertOrPanic(array[1] == 2);
107}
108
109test "array child property" {
110 var x: [5]i32 = undefined;
111 assertOrPanic(@typeOf(x).Child == i32);
112}
113
114test "array len property" {
115 var x: [5]i32 = undefined;
116 assertOrPanic(@typeOf(x).len == 5);
117}
118
119test "array len field" {
120 var arr = [4]u8{ 0, 0, 0, 0 };
121 var ptr = &arr;
122 assertOrPanic(arr.len == 4);
123 comptime assertOrPanic(arr.len == 4);
124 assertOrPanic(ptr.len == 4);
125 comptime assertOrPanic(ptr.len == 4);
126}
127
128test "single-item pointer to array indexing and slicing" {
129 testSingleItemPtrArrayIndexSlice();
130 comptime testSingleItemPtrArrayIndexSlice();
131}
132
133fn testSingleItemPtrArrayIndexSlice() void {
134 var array = "aaaa";
135 doSomeMangling(&array);
136 assertOrPanic(mem.eql(u8, "azya", array));
137}
138
139fn doSomeMangling(array: *[4]u8) void {
140 array[1] = 'z';
141 array[2..3][0] = 'y';
142}
143
144test "implicit cast single-item pointer" {
145 testImplicitCastSingleItemPtr();
146 comptime testImplicitCastSingleItemPtr();
147}
148
149fn testImplicitCastSingleItemPtr() void {
150 var byte: u8 = 100;
151 const slice = (*[1]u8)(&byte)[0..];
152 slice[0] += 1;
153 assertOrPanic(byte == 101);
154}
155
156fn testArrayByValAtComptime(b: [2]u8) u8 {
157 return b[0];
158}
159
160test "comptime evalutating function that takes array by value" {
161 const arr = []u8{ 0, 1 };
162 _ = comptime testArrayByValAtComptime(arr);
163 _ = comptime testArrayByValAtComptime(arr);
164}
165
166test "implicit comptime in array type size" {
167 var arr: [plusOne(10)]bool = undefined;
168 assertOrPanic(arr.len == 11);
169}
170
171fn plusOne(x: u32) u32 {
172 return x + 1;
173}
174
175test "array literal as argument to function" {
176 const S = struct {
177 fn entry(two: i32) void {
178 foo([]i32{
179 1,
180 2,
181 3,
182 });
183 foo([]i32{
184 1,
185 two,
186 3,
187 });
188 foo2(true, []i32{
189 1,
190 2,
191 3,
192 });
193 foo2(true, []i32{
194 1,
195 two,
196 3,
197 });
198 }
199 fn foo(x: []const i32) void {
200 assertOrPanic(x[0] == 1);
201 assertOrPanic(x[1] == 2);
202 assertOrPanic(x[2] == 3);
203 }
204 fn foo2(trash: bool, x: []const i32) void {
205 assertOrPanic(trash);
206 assertOrPanic(x[0] == 1);
207 assertOrPanic(x[1] == 2);
208 assertOrPanic(x[2] == 3);
209 }
210 };
211 S.entry(2);
212 comptime S.entry(2);
213}
214
215test "double nested array to const slice cast in array literal" {
216 const S = struct {
217 fn entry(two: i32) void {
218 const cases = [][]const []const i32{
219 [][]const i32{[]i32{1}},
220 [][]const i32{[]i32{ 2, 3 }},
221 [][]const i32{
222 []i32{4},
223 []i32{ 5, 6, 7 },
224 },
225 };
226 check(cases);
227
228 const cases2 = [][]const i32{
229 []i32{1},
230 []i32{ two, 3 },
231 };
232 assertOrPanic(cases2.len == 2);
233 assertOrPanic(cases2[0].len == 1);
234 assertOrPanic(cases2[0][0] == 1);
235 assertOrPanic(cases2[1].len == 2);
236 assertOrPanic(cases2[1][0] == 2);
237 assertOrPanic(cases2[1][1] == 3);
238
239 const cases3 = [][]const []const i32{
240 [][]const i32{[]i32{1}},
241 [][]const i32{[]i32{ two, 3 }},
242 [][]const i32{
243 []i32{4},
244 []i32{ 5, 6, 7 },
245 },
246 };
247 check(cases3);
248 }
249
250 fn check(cases: []const []const []const i32) void {
251 assertOrPanic(cases.len == 3);
252 assertOrPanic(cases[0].len == 1);
253 assertOrPanic(cases[0][0].len == 1);
254 assertOrPanic(cases[0][0][0] == 1);
255 assertOrPanic(cases[1].len == 1);
256 assertOrPanic(cases[1][0].len == 2);
257 assertOrPanic(cases[1][0][0] == 2);
258 assertOrPanic(cases[1][0][1] == 3);
259 assertOrPanic(cases[2].len == 2);
260 assertOrPanic(cases[2][0].len == 1);
261 assertOrPanic(cases[2][0][0] == 4);
262 assertOrPanic(cases[2][1].len == 3);
263 assertOrPanic(cases[2][1][0] == 5);
264 assertOrPanic(cases[2][1][1] == 6);
265 assertOrPanic(cases[2][1][2] == 7);
266 }
267 };
268 S.entry(2);
269 comptime S.entry(2);
270}
test/stage1/behavior/asm.zig created+92
......@@ -0,0 +1,92 @@
1const config = @import("builtin");
2const assertOrPanic = @import("std").debug.assertOrPanic;
3
4comptime {
5 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
6 asm volatile (
7 \\.globl aoeu;
8 \\.type aoeu, @function;
9 \\.set aoeu, derp;
10 );
11 }
12}
13
14test "module level assembly" {
15 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
16 assertOrPanic(aoeu() == 1234);
17 }
18}
19
20test "output constraint modifiers" {
21 // This is only testing compilation.
22 var a: u32 = 3;
23 asm volatile (""
24 : [_] "=m,r" (a)
25 :
26 : ""
27 );
28 asm volatile (""
29 : [_] "=r,m" (a)
30 :
31 : ""
32 );
33}
34
35test "alternative constraints" {
36 // Make sure we allow commas as a separator for alternative constraints.
37 var a: u32 = 3;
38 asm volatile (""
39 : [_] "=r,m" (a)
40 : [_] "r,m" (a)
41 : ""
42 );
43}
44
45test "sized integer/float in asm input" {
46 asm volatile (""
47 :
48 : [_] "m" (usize(3))
49 : ""
50 );
51 asm volatile (""
52 :
53 : [_] "m" (i15(-3))
54 : ""
55 );
56 asm volatile (""
57 :
58 : [_] "m" (u3(3))
59 : ""
60 );
61 asm volatile (""
62 :
63 : [_] "m" (i3(3))
64 : ""
65 );
66 asm volatile (""
67 :
68 : [_] "m" (u121(3))
69 : ""
70 );
71 asm volatile (""
72 :
73 : [_] "m" (i121(3))
74 : ""
75 );
76 asm volatile (""
77 :
78 : [_] "m" (f32(3.17))
79 : ""
80 );
81 asm volatile (""
82 :
83 : [_] "m" (f64(3.17))
84 : ""
85 );
86}
87
88extern fn aoeu() i32;
89
90export fn derp() i32 {
91 return 1234;
92}
test/stage1/behavior/atomics.zig created+71
......@@ -0,0 +1,71 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;
6
7test "cmpxchg" {
8 var x: i32 = 1234;
9 if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
10 assertOrPanic(x1 == 1234);
11 } else {
12 @panic("cmpxchg should have failed");
13 }
14
15 while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
16 assertOrPanic(x1 == 1234);
17 }
18 assertOrPanic(x == 5678);
19
20 assertOrPanic(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
21 assertOrPanic(x == 42);
22}
23
24test "fence" {
25 var x: i32 = 1234;
26 @fence(AtomicOrder.SeqCst);
27 x = 5678;
28}
29
30test "atomicrmw and atomicload" {
31 var data: u8 = 200;
32 testAtomicRmw(&data);
33 assertOrPanic(data == 42);
34 testAtomicLoad(&data);
35}
36
37fn testAtomicRmw(ptr: *u8) void {
38 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
39 assertOrPanic(prev_value == 200);
40 comptime {
41 var x: i32 = 1234;
42 const y: i32 = 12345;
43 assertOrPanic(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
44 assertOrPanic(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
45 }
46}
47
48fn testAtomicLoad(ptr: *u8) void {
49 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
50 assertOrPanic(x == 42);
51}
52
53test "cmpxchg with ptr" {
54 var data1: i32 = 1234;
55 var data2: i32 = 5678;
56 var data3: i32 = 9101;
57 var x: *i32 = &data1;
58 if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
59 assertOrPanic(x1 == &data1);
60 } else {
61 @panic("cmpxchg should have failed");
62 }
63
64 while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
65 assertOrPanic(x1 == &data1);
66 }
67 assertOrPanic(x == &data3);
68
69 assertOrPanic(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
70 assertOrPanic(x == &data2);
71}
test/stage1/behavior/bit_shifting.zig created+88
......@@ -0,0 +1,88 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 assertOrPanic(Key == @IntType(false, Key.bit_count));
6 assertOrPanic(Key.bit_count >= mask_bit_count);
7 const ShardKey = @IntType(false, mask_bit_count);
8 const shift_amount = Key.bit_count - ShardKey.bit_count;
9 return struct {
10 const Self = @This();
11 shards: [1 << ShardKey.bit_count]?*Node,
12
13 pub fn create() Self {
14 return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) };
15 }
16
17 fn getShardKey(key: Key) ShardKey {
18 // https://github.com/ziglang/zig/issues/1544
19 // this special case is needed because you can't u32 >> 32.
20 if (ShardKey == u0) return 0;
21
22 // this can be u1 >> u0
23 const shard_key = key >> shift_amount;
24
25 // TODO: https://github.com/ziglang/zig/issues/1544
26 // This cast could be implicit if we teach the compiler that
27 // u32 >> 30 -> u2
28 return @intCast(ShardKey, shard_key);
29 }
30
31 pub fn put(self: *Self, node: *Node) void {
32 const shard_key = Self.getShardKey(node.key);
33 node.next = self.shards[shard_key];
34 self.shards[shard_key] = node;
35 }
36
37 pub fn get(self: *Self, key: Key) ?*Node {
38 const shard_key = Self.getShardKey(key);
39 var maybe_node = self.shards[shard_key];
40 while (maybe_node) |node| : (maybe_node = node.next) {
41 if (node.key == key) return node;
42 }
43 return null;
44 }
45
46 pub const Node = struct {
47 key: Key,
48 value: V,
49 next: ?*Node,
50
51 pub fn init(self: *Node, key: Key, value: V) void {
52 self.key = key;
53 self.value = value;
54 self.next = null;
55 }
56 };
57 };
58}
59
60test "sharded table" {
61 // realistic 16-way sharding
62 testShardedTable(u32, 4, 8);
63
64 testShardedTable(u5, 0, 32); // ShardKey == u0
65 testShardedTable(u5, 2, 32);
66 testShardedTable(u5, 5, 32);
67
68 testShardedTable(u1, 0, 2);
69 testShardedTable(u1, 1, 2); // this does u1 >> u0
70
71 testShardedTable(u0, 0, 1);
72}
73fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void {
74 const Table = ShardedTable(Key, mask_bit_count, void);
75
76 var table = Table.create();
77 var node_buffer: [node_count]Table.Node = undefined;
78 for (node_buffer) |*node, i| {
79 const key = @intCast(Key, i);
80 assertOrPanic(table.get(key) == null);
81 node.init(key, {});
82 table.put(node);
83 }
84
85 for (node_buffer) |*node, i| {
86 assertOrPanic(table.get(@intCast(Key, i)) == node);
87 }
88}
test/stage1/behavior/bitcast.zig created+36
......@@ -0,0 +1,36 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const maxInt = std.math.maxInt;
4
5test "@bitCast i32 -> u32" {
6 testBitCast_i32_u32();
7 comptime testBitCast_i32_u32();
8}
9
10fn testBitCast_i32_u32() void {
11 assertOrPanic(conv(-1) == maxInt(u32));
12 assertOrPanic(conv2(maxInt(u32)) == -1);
13}
14
15fn conv(x: i32) u32 {
16 return @bitCast(u32, x);
17}
18fn conv2(x: u32) i32 {
19 return @bitCast(i32, x);
20}
21
22test "@bitCast extern enum to its integer type" {
23 const SOCK = extern enum {
24 A,
25 B,
26
27 fn testBitCastExternEnum() void {
28 var SOCK_DGRAM = @This().B;
29 var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
30 assertOrPanic(sock_dgram == 1);
31 }
32 };
33
34 SOCK.testBitCastExternEnum();
35 comptime SOCK.testBitCastExternEnum();
36}
test/stage1/behavior/bitreverse.zig created+81
......@@ -0,0 +1,81 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const minInt = std.math.minInt;
4
5test "@bitreverse" {
6 comptime testBitReverse();
7 testBitReverse();
8}
9
10fn testBitReverse() void {
11 // using comptime_ints, unsigned
12 assertOrPanic(@bitreverse(u0, 0) == 0);
13 assertOrPanic(@bitreverse(u5, 0x12) == 0x9);
14 assertOrPanic(@bitreverse(u8, 0x12) == 0x48);
15 assertOrPanic(@bitreverse(u16, 0x1234) == 0x2c48);
16 assertOrPanic(@bitreverse(u24, 0x123456) == 0x6a2c48);
17 assertOrPanic(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
18 assertOrPanic(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
19 assertOrPanic(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 assertOrPanic(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 assertOrPanic(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 assertOrPanic(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 assertOrPanic(@bitreverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 assertOrPanic(@bitreverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 assertOrPanic(@bitreverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 assertOrPanic(@bitreverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 assertOrPanic(@bitreverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 assertOrPanic(@bitreverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 assertOrPanic(@bitreverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 assertOrPanic(@bitreverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 assertOrPanic(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 assertOrPanic(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 assertOrPanic(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 assertOrPanic(@bitreverse(i0, 0) == 0);
50 assertOrPanic(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49)));
51 assertOrPanic(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48)));
52 assertOrPanic(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48)));
53 assertOrPanic(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48)));
54 assertOrPanic(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48)));
55 assertOrPanic(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48)));
56 assertOrPanic(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48)));
57 assertOrPanic(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48)));
58 assertOrPanic(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48)));
59
60 // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
61 var neg5: i5 = minInt(i5) + 1;
62 assertOrPanic(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
63 var neg8: i8 = -18;
64 assertOrPanic(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
65 var neg16: i16 = -32694;
66 assertOrPanic(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
67 var neg24: i24 = -6773785;
68 assertOrPanic(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
69 var neg32: i32 = -16773785;
70 assertOrPanic(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
71 var neg40: i40 = minInt(i40) + 12345;
72 assertOrPanic(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
73 var neg48: i48 = minInt(i48) + 12345;
74 assertOrPanic(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
75 var neg56: i56 = minInt(i56) + 12345;
76 assertOrPanic(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
77 var neg64: i64 = minInt(i64) + 12345;
78 assertOrPanic(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
79 var neg128: i128 = minInt(i128) + 12345;
80 assertOrPanic(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
81}
test/stage1/behavior/bool.zig created+35
......@@ -0,0 +1,35 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "bool literals" {
4 assertOrPanic(true);
5 assertOrPanic(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 assertOrPanic(@boolToInt(t) == u32(1));
12 assertOrPanic(@boolToInt(f) == u32(0));
13 nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) void {
17 assertOrPanic(@boolToInt(t) == u32(1));
18 assertOrPanic(@boolToInt(f) == u32(0));
19}
20
21test "bool cmp" {
22 assertOrPanic(testBoolCmp(true, false) == false);
23}
24fn testBoolCmp(a: bool, b: bool) bool {
25 return a == b;
26}
27
28const global_f = false;
29const global_t = true;
30const not_global_f = !global_f;
31const not_global_t = !global_t;
32test "compile time bool not" {
33 assertOrPanic(not_global_f);
34 assertOrPanic(!not_global_t);
35}
test/stage1/behavior/bswap.zig created+32
......@@ -0,0 +1,32 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "@bswap" {
5 comptime testByteSwap();
6 testByteSwap();
7}
8
9fn testByteSwap() void {
10 assertOrPanic(@bswap(u0, 0) == 0);
11 assertOrPanic(@bswap(u8, 0x12) == 0x12);
12 assertOrPanic(@bswap(u16, 0x1234) == 0x3412);
13 assertOrPanic(@bswap(u24, 0x123456) == 0x563412);
14 assertOrPanic(@bswap(u32, 0x12345678) == 0x78563412);
15 assertOrPanic(@bswap(u40, 0x123456789a) == 0x9a78563412);
16 assertOrPanic(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
17 assertOrPanic(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 assertOrPanic(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 assertOrPanic(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
20
21 assertOrPanic(@bswap(i0, 0) == 0);
22 assertOrPanic(@bswap(i8, -50) == -50);
23 assertOrPanic(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 assertOrPanic(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 assertOrPanic(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 assertOrPanic(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
27 assertOrPanic(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 assertOrPanic(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 assertOrPanic(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 assertOrPanic(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
32}
test/stage1/behavior/bugs/1076.zig created+16
......@@ -0,0 +1,16 @@
1const std = @import("std");
2const mem = std.mem;
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "comptime code should not modify constant data" {
6 testCastPtrOfArrayToSliceAndPtr();
7 comptime testCastPtrOfArrayToSliceAndPtr();
8}
9
10fn testCastPtrOfArrayToSliceAndPtr() void {
11 var array = "aoeu";
12 const x: [*]u8 = &array;
13 x[0] += 1;
14 assertOrPanic(mem.eql(u8, array[0..], "boeu"));
15}
16
test/stage1/behavior/bugs/1111.zig created+12
......@@ -0,0 +1,12 @@
1const Foo = extern enum {
2 Bar = -1,
3};
4
5test "issue 1111 fixed" {
6 const v = Foo.Bar;
7
8 switch (v) {
9 Foo.Bar => return,
10 else => return,
11 }
12}
test/stage1/behavior/bugs/1277.zig created+15
......@@ -0,0 +1,15 @@
1const std = @import("std");
2
3const S = struct {
4 f: ?fn () i32,
5};
6
7const s = S{ .f = f };
8
9fn f() i32 {
10 return 1234;
11}
12
13test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
14 std.debug.assertOrPanic(s.f.?() == 1234);
15}
test/stage1/behavior/bugs/1322.zig created+19
......@@ -0,0 +1,19 @@
1const std = @import("std");
2
3const B = union(enum) {
4 c: C,
5 None,
6};
7
8const A = struct {
9 b: B,
10};
11
12const C = struct {};
13
14test "tagged union with all void fields but a meaningful tag" {
15 var a: A = A{ .b = B{ .c = C{} } };
16 std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).c);
17 a = A{ .b = B.None };
18 std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).None);
19}
test/stage1/behavior/bugs/1381.zig created+21
......@@ -0,0 +1,21 @@
1const std = @import("std");
2
3const B = union(enum) {
4 D: u8,
5 E: u16,
6};
7
8const A = union(enum) {
9 B: B,
10 C: u8,
11};
12
13test "union that needs padding bytes inside an array" {
14 var as = []A{
15 A{ .B = B{ .D = 1 } },
16 A{ .B = B{ .D = 1 } },
17 };
18
19 const a = as[0].B;
20 std.debug.assertOrPanic(a.D == 1);
21}
test/stage1/behavior/bugs/1421.zig created+14
......@@ -0,0 +1,14 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assertOrPanic = std.debug.assertOrPanic;
4
5const S = struct {
6 fn method() builtin.TypeInfo {
7 return @typeInfo(S);
8 }
9};
10
11test "functions with return type required to be comptime are generic" {
12 const ti = S.method();
13 assertOrPanic(builtin.TypeId(ti) == builtin.TypeId.Struct);
14}
test/stage1/behavior/bugs/1442.zig created+11
......@@ -0,0 +1,11 @@
1const std = @import("std");
2
3const Union = union(enum) {
4 Text: []const u8,
5 Color: u32,
6};
7
8test "const error union field alignment" {
9 var union_or_err: anyerror!Union = Union{ .Color = 1234 };
10 std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
11}
test/stage1/behavior/bugs/1486.zig created+11
......@@ -0,0 +1,11 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 assertOrPanic(&global == ptr);
9 assertOrPanic(ptr.* == 1234);
10}
11
test/stage1/behavior/bugs/394.zig created+18
......@@ -0,0 +1,18 @@
1const E = union(enum) {
2 A: [9]u8,
3 B: u64,
4};
5const S = struct {
6 x: u8,
7 y: E,
8};
9
10const assertOrPanic = @import("std").debug.assertOrPanic;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 assertOrPanic(x.x == 3);
18}
test/stage1/behavior/bugs/655.zig created+12
......@@ -0,0 +1,12 @@
1const std = @import("std");
2const other_file = @import("655_other_file.zig");
3
4test "function with *const parameter with type dereferenced by namespace" {
5 const x: other_file.Integer = 1234;
6 comptime std.debug.assertOrPanic(@typeOf(&x) == *const other_file.Integer);
7 foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) void {
11 std.debug.assertOrPanic(x.* == 1234);
12}
test/stage1/behavior/bugs/655_other_file.zig created+1
......@@ -0,0 +1 @@
1pub const Integer = u32;
test/stage1/behavior/bugs/656.zig created+31
......@@ -0,0 +1,31 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const PrefixOp = union(enum) {
4 Return,
5 AddrOf: Value,
6};
7
8const Value = struct {
9 align_expr: ?u32,
10};
11
12test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
13 foo(false, true);
14}
15
16fn foo(a: bool, b: bool) void {
17 var prefix_op = PrefixOp{
18 .AddrOf = Value{ .align_expr = 1234 },
19 };
20 if (a) {} else {
21 switch (prefix_op) {
22 PrefixOp.AddrOf => |addr_of_info| {
23 if (b) {}
24 if (addr_of_info.align_expr) |align_expr| {
25 assertOrPanic(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/stage1/behavior/bugs/726.zig created+16
......@@ -0,0 +1,16 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 assertOrPanic(x.?.* == 4);
7}
8
9test "@ptrCast from var in empty struct to nullable" {
10 const container = struct {
11 var c: u8 = 4;
12 };
13 var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
14 assertOrPanic(x.?.* == 4);
15}
16
test/stage1/behavior/bugs/828.zig created+33
......@@ -0,0 +1,33 @@
1const CountBy = struct {
2 a: usize,
3
4 const One = CountBy{ .a = 1 };
5
6 pub fn counter(self: *const CountBy) Counter {
7 return Counter{ .i = 0 };
8 }
9};
10
11const Counter = struct {
12 i: usize,
13
14 pub fn count(self: *Counter) bool {
15 self.i += 1;
16 return self.i <= 10;
17 }
18};
19
20fn constCount(comptime cb: *const CountBy, comptime unused: u32) void {
21 comptime {
22 var cnt = cb.counter();
23 if (cnt.i != 0) @compileError("Counter instance reused!");
24 while (cnt.count()) {}
25 }
26}
27
28test "comptime struct return should not return the same instance" {
29 //the first parameter must be passed by reference to trigger the bug
30 //a second parameter is required to trigger the bug
31 const ValA = constCount(&CountBy.One, 12);
32 const ValB = constCount(&CountBy.One, 15);
33}
test/stage1/behavior/bugs/920.zig created+65
......@@ -0,0 +1,65 @@
1const std = @import("std");
2const math = std.math;
3const Random = std.rand.Random;
4
5const ZigTable = struct {
6 r: f64,
7 x: [257]f64,
8 f: [257]f64,
9
10 pdf: fn (f64) f64,
11 is_symmetric: bool,
12 zero_case: fn (*Random, f64) f64,
13};
14
15fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable {
16 var tables: ZigTable = undefined;
17
18 tables.is_symmetric = is_symmetric;
19 tables.r = r;
20 tables.pdf = f;
21 tables.zero_case = zero_case;
22
23 tables.x[0] = v / f(r);
24 tables.x[1] = r;
25
26 for (tables.x[2..256]) |*entry, i| {
27 const last = tables.x[2 + i - 1];
28 entry.* = f_inv(v / last + f(last));
29 }
30 tables.x[256] = 0;
31
32 for (tables.f[0..]) |*entry, i| {
33 entry.* = f(tables.x[i]);
34 }
35
36 return tables;
37}
38
39const norm_r = 3.6541528853610088;
40const norm_v = 0.00492867323399;
41
42fn norm_f(x: f64) f64 {
43 return math.exp(-x * x / 2.0);
44}
45fn norm_f_inv(y: f64) f64 {
46 return math.sqrt(-2.0 * math.ln(y));
47}
48fn norm_zero_case(random: *Random, u: f64) f64 {
49 return 0.0;
50}
51
52const NormalDist = blk: {
53 @setEvalBranchQuota(30000);
54 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
55};
56
57test "bug 920 fixed" {
58 const NormalDist1 = blk: {
59 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
60 };
61
62 for (NormalDist1.f) |_, i| {
63 std.debug.assertOrPanic(NormalDist1.f[i] == NormalDist.f[i]);
64 }
65}
test/stage1/behavior/byval_arg_var.zig created+27
......@@ -0,0 +1,27 @@
1const std = @import("std");
2
3var result: []const u8 = "wrong";
4
5test "pass string literal byvalue to a generic var param" {
6 start();
7 blowUpStack(10);
8
9 std.debug.assertOrPanic(std.mem.eql(u8, result, "string literal"));
10}
11
12fn start() void {
13 foo("string literal");
14}
15
16fn foo(x: var) void {
17 bar(x);
18}
19
20fn bar(x: var) void {
21 result = x;
22}
23
24fn blowUpStack(x: u32) void {
25 if (x == 0) return;
26 blowUpStack(x - 1);
27}
test/stage1/behavior/cancel.zig created+92
......@@ -0,0 +1,92 @@
1const std = @import("std");
2
3var defer_f1: bool = false;
4var defer_f2: bool = false;
5var defer_f3: bool = false;
6
7test "cancel forwards" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = async<&da.allocator> f1() catch unreachable;
12 cancel p;
13 std.debug.assertOrPanic(defer_f1);
14 std.debug.assertOrPanic(defer_f2);
15 std.debug.assertOrPanic(defer_f3);
16}
17
18async fn f1() void {
19 defer {
20 defer_f1 = true;
21 }
22 await (async f2() catch unreachable);
23}
24
25async fn f2() void {
26 defer {
27 defer_f2 = true;
28 }
29 await (async f3() catch unreachable);
30}
31
32async fn f3() void {
33 defer {
34 defer_f3 = true;
35 }
36 suspend;
37}
38
39var defer_b1: bool = false;
40var defer_b2: bool = false;
41var defer_b3: bool = false;
42var defer_b4: bool = false;
43
44test "cancel backwards" {
45 var da = std.heap.DirectAllocator.init();
46 defer da.deinit();
47
48 const p = async<&da.allocator> b1() catch unreachable;
49 cancel p;
50 std.debug.assertOrPanic(defer_b1);
51 std.debug.assertOrPanic(defer_b2);
52 std.debug.assertOrPanic(defer_b3);
53 std.debug.assertOrPanic(defer_b4);
54}
55
56async fn b1() void {
57 defer {
58 defer_b1 = true;
59 }
60 await (async b2() catch unreachable);
61}
62
63var b4_handle: promise = undefined;
64
65async fn b2() void {
66 const b3_handle = async b3() catch unreachable;
67 resume b4_handle;
68 cancel b4_handle;
69 defer {
70 defer_b2 = true;
71 }
72 const value = await b3_handle;
73 @panic("unreachable");
74}
75
76async fn b3() i32 {
77 defer {
78 defer_b3 = true;
79 }
80 await (async b4() catch unreachable);
81 return 1234;
82}
83
84async fn b4() void {
85 defer {
86 defer_b4 = true;
87 }
88 suspend {
89 b4_handle = @handle();
90 }
91 suspend;
92}
test/stage1/behavior/cast.zig created+473
......@@ -0,0 +1,473 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5
6test "int to ptr cast" {
7 const x = usize(13);
8 const y = @intToPtr(*u8, x);
9 const z = @ptrToInt(y);
10 assertOrPanic(z == 13);
11}
12
13test "integer literal to pointer cast" {
14 const vga_mem = @intToPtr(*u16, 0xB8000);
15 assertOrPanic(@ptrToInt(vga_mem) == 0xB8000);
16}
17
18test "pointer reinterpret const float to int" {
19 const float: f64 = 5.99999999999994648725e-01;
20 const float_ptr = &float;
21 const int_ptr = @ptrCast(*const i32, float_ptr);
22 const int_val = int_ptr.*;
23 assertOrPanic(int_val == 858993411);
24}
25
26test "implicitly cast indirect pointer to maybe-indirect pointer" {
27 const S = struct {
28 const Self = @This();
29 x: u8,
30 fn constConst(p: *const *const Self) u8 {
31 return p.*.x;
32 }
33 fn maybeConstConst(p: ?*const *const Self) u8 {
34 return p.?.*.x;
35 }
36 fn constConstConst(p: *const *const *const Self) u8 {
37 return p.*.*.x;
38 }
39 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
40 return p.?.*.*.x;
41 }
42 };
43 const s = S{ .x = 42 };
44 const p = &s;
45 const q = &p;
46 const r = &q;
47 assertOrPanic(42 == S.constConst(q));
48 assertOrPanic(42 == S.maybeConstConst(q));
49 assertOrPanic(42 == S.constConstConst(r));
50 assertOrPanic(42 == S.maybeConstConstConst(r));
51}
52
53test "explicit cast from integer to error type" {
54 testCastIntToErr(error.ItBroke);
55 comptime testCastIntToErr(error.ItBroke);
56}
57fn testCastIntToErr(err: anyerror) void {
58 const x = @errorToInt(err);
59 const y = @intToError(x);
60 assertOrPanic(error.ItBroke == y);
61}
62
63test "peer resolve arrays of different size to const slice" {
64 assertOrPanic(mem.eql(u8, boolToStr(true), "true"));
65 assertOrPanic(mem.eql(u8, boolToStr(false), "false"));
66 comptime assertOrPanic(mem.eql(u8, boolToStr(true), "true"));
67 comptime assertOrPanic(mem.eql(u8, boolToStr(false), "false"));
68}
69fn boolToStr(b: bool) []const u8 {
70 return if (b) "true" else "false";
71}
72
73test "peer resolve array and const slice" {
74 testPeerResolveArrayConstSlice(true);
75 comptime testPeerResolveArrayConstSlice(true);
76}
77fn testPeerResolveArrayConstSlice(b: bool) void {
78 const value1 = if (b) "aoeu" else ([]const u8)("zz");
79 const value2 = if (b) ([]const u8)("zz") else "aoeu";
80 assertOrPanic(mem.eql(u8, value1, "aoeu"));
81 assertOrPanic(mem.eql(u8, value2, "zz"));
82}
83
84test "implicitly cast from T to anyerror!?T" {
85 castToOptionalTypeError(1);
86 comptime castToOptionalTypeError(1);
87}
88
89const A = struct {
90 a: i32,
91};
92fn castToOptionalTypeError(z: i32) void {
93 const x = i32(1);
94 const y: anyerror!?i32 = x;
95 assertOrPanic((try y).? == 1);
96
97 const f = z;
98 const g: anyerror!?i32 = f;
99
100 const a = A{ .a = z };
101 const b: anyerror!?A = a;
102 assertOrPanic((b catch unreachable).?.a == 1);
103}
104
105test "implicitly cast from int to anyerror!?T" {
106 implicitIntLitToOptional();
107 comptime implicitIntLitToOptional();
108}
109fn implicitIntLitToOptional() void {
110 const f: ?i32 = 1;
111 const g: anyerror!?i32 = 1;
112}
113
114test "return null from fn() anyerror!?&T" {
115 const a = returnNullFromOptionalTypeErrorRef();
116 const b = returnNullLitFromOptionalTypeErrorRef();
117 assertOrPanic((try a) == null and (try b) == null);
118}
119fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
120 const a: ?*A = null;
121 return a;
122}
123fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
124 return null;
125}
126
127test "peer type resolution: ?T and T" {
128 assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0);
129 assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3);
130 comptime {
131 assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0);
132 assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3);
133 }
134}
135fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
136 if (c) {
137 return if (b) null else usize(0);
138 }
139
140 return usize(3);
141}
142
143test "peer type resolution: [0]u8 and []const u8" {
144 assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
145 assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
146 comptime {
147 assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
148 assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
149 }
150}
151fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
152 if (a) {
153 return []const u8{};
154 }
155
156 return slice[0..1];
157}
158
159test "implicitly cast from [N]T to ?[]const T" {
160 assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi"));
161 comptime assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi"));
162}
163
164fn castToOptionalSlice() ?[]const u8 {
165 return "hi";
166}
167
168test "implicitly cast from [0]T to anyerror![]T" {
169 testCastZeroArrayToErrSliceMut();
170 comptime testCastZeroArrayToErrSliceMut();
171}
172
173fn testCastZeroArrayToErrSliceMut() void {
174 assertOrPanic((gimmeErrOrSlice() catch unreachable).len == 0);
175}
176
177fn gimmeErrOrSlice() anyerror![]u8 {
178 return []u8{};
179}
180
181test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
182 {
183 var data = "hi";
184 const slice = data[0..];
185 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
186 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
187 }
188 comptime {
189 var data = "hi";
190 const slice = data[0..];
191 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
192 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
193 }
194}
195fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
196 if (a) {
197 return []u8{};
198 }
199
200 return slice[0..1];
201}
202
203test "resolve undefined with integer" {
204 testResolveUndefWithInt(true, 1234);
205 comptime testResolveUndefWithInt(true, 1234);
206}
207fn testResolveUndefWithInt(b: bool, x: i32) void {
208 const value = if (b) x else undefined;
209 if (b) {
210 assertOrPanic(value == x);
211 }
212}
213
214test "implicit cast from &const [N]T to []const T" {
215 testCastConstArrayRefToConstSlice();
216 comptime testCastConstArrayRefToConstSlice();
217}
218
219fn testCastConstArrayRefToConstSlice() void {
220 const blah = "aoeu";
221 const const_array_ref = &blah;
222 assertOrPanic(@typeOf(const_array_ref) == *const [4]u8);
223 const slice: []const u8 = const_array_ref;
224 assertOrPanic(mem.eql(u8, slice, "aoeu"));
225}
226
227test "peer type resolution: error and [N]T" {
228 // TODO: implicit error!T to error!U where T can implicitly cast to U
229 //assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
230 //comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
231 assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
232 comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
233}
234
235//fn testPeerErrorAndArray(x: u8) error![]const u8 {
236// return switch (x) {
237// 0x00 => "OK",
238// else => error.BadValue,
239// };
240//}
241fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
242 return switch (x) {
243 0x00 => "OK",
244 0x01 => "OKK",
245 else => error.BadValue,
246 };
247}
248
249test "@floatToInt" {
250 testFloatToInts();
251 comptime testFloatToInts();
252}
253
254fn testFloatToInts() void {
255 const x = i32(1e4);
256 assertOrPanic(x == 10000);
257 const y = @floatToInt(i32, f32(1e4));
258 assertOrPanic(y == 10000);
259 expectFloatToInt(f16, 255.1, u8, 255);
260 expectFloatToInt(f16, 127.2, i8, 127);
261 expectFloatToInt(f16, -128.2, i8, -128);
262 expectFloatToInt(f32, 255.1, u8, 255);
263 expectFloatToInt(f32, 127.2, i8, 127);
264 expectFloatToInt(f32, -128.2, i8, -128);
265 expectFloatToInt(comptime_int, 1234, i16, 1234);
266}
267
268fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
269 assertOrPanic(@floatToInt(I, f) == i);
270}
271
272test "cast u128 to f128 and back" {
273 comptime testCast128();
274 testCast128();
275}
276
277fn testCast128() void {
278 assertOrPanic(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
279}
280
281fn cast128Int(x: f128) u128 {
282 return @bitCast(u128, x);
283}
284
285fn cast128Float(x: u128) f128 {
286 return @bitCast(f128, x);
287}
288
289test "const slice widen cast" {
290 const bytes align(4) = []u8{
291 0x12,
292 0x12,
293 0x12,
294 0x12,
295 };
296
297 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
298 assertOrPanic(u32_value == 0x12121212);
299
300 assertOrPanic(@bitCast(u32, bytes) == 0x12121212);
301}
302
303test "single-item pointer of array to slice and to unknown length pointer" {
304 testCastPtrOfArrayToSliceAndPtr();
305 comptime testCastPtrOfArrayToSliceAndPtr();
306}
307
308fn testCastPtrOfArrayToSliceAndPtr() void {
309 var array = "aoeu";
310 const x: [*]u8 = &array;
311 x[0] += 1;
312 assertOrPanic(mem.eql(u8, array[0..], "boeu"));
313 const y: []u8 = &array;
314 y[0] += 1;
315 assertOrPanic(mem.eql(u8, array[0..], "coeu"));
316}
317
318test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
319 const window_name = [1][*]const u8{c"window name"};
320 const x: [*]const ?[*]const u8 = &window_name;
321 assertOrPanic(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
322}
323
324test "@intCast comptime_int" {
325 const result = @intCast(i32, 1234);
326 assertOrPanic(@typeOf(result) == i32);
327 assertOrPanic(result == 1234);
328}
329
330test "@floatCast comptime_int and comptime_float" {
331 {
332 const result = @floatCast(f16, 1234);
333 assertOrPanic(@typeOf(result) == f16);
334 assertOrPanic(result == 1234.0);
335 }
336 {
337 const result = @floatCast(f16, 1234.0);
338 assertOrPanic(@typeOf(result) == f16);
339 assertOrPanic(result == 1234.0);
340 }
341 {
342 const result = @floatCast(f32, 1234);
343 assertOrPanic(@typeOf(result) == f32);
344 assertOrPanic(result == 1234.0);
345 }
346 {
347 const result = @floatCast(f32, 1234.0);
348 assertOrPanic(@typeOf(result) == f32);
349 assertOrPanic(result == 1234.0);
350 }
351}
352
353test "comptime_int @intToFloat" {
354 {
355 const result = @intToFloat(f16, 1234);
356 assertOrPanic(@typeOf(result) == f16);
357 assertOrPanic(result == 1234.0);
358 }
359 {
360 const result = @intToFloat(f32, 1234);
361 assertOrPanic(@typeOf(result) == f32);
362 assertOrPanic(result == 1234.0);
363 }
364}
365
366test "@bytesToSlice keeps pointer alignment" {
367 var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
368 const numbers = @bytesToSlice(u32, bytes[0..]);
369 comptime assertOrPanic(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
370}
371
372test "@intCast i32 to u7" {
373 var x: u128 = maxInt(u128);
374 var y: i32 = 120;
375 var z = x >> @intCast(u7, y);
376 assertOrPanic(z == 0xff);
377}
378
379test "implicit cast undefined to optional" {
380 assertOrPanic(MakeType(void).getNull() == null);
381 assertOrPanic(MakeType(void).getNonNull() != null);
382}
383
384fn MakeType(comptime T: type) type {
385 return struct {
386 fn getNull() ?T {
387 return null;
388 }
389
390 fn getNonNull() ?T {
391 return T(undefined);
392 }
393 };
394}
395
396test "implicit cast from *[N]T to ?[*]T" {
397 var x: ?[*]u16 = null;
398 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
399
400 x = &y;
401 assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4]));
402 x.?[0] = 8;
403 y[3] = 6;
404 assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4]));
405}
406
407test "implicit cast from *T to ?*c_void" {
408 var a: u8 = 1;
409 incrementVoidPtrValue(&a);
410 std.debug.assertOrPanic(a == 2);
411}
412
413fn incrementVoidPtrValue(value: ?*c_void) void {
414 @ptrCast(*u8, value.?).* += 1;
415}
416
417test "implicit cast from [*]T to ?*c_void" {
418 var a = []u8{ 3, 2, 1 };
419 incrementVoidPtrArray(a[0..].ptr, 3);
420 assertOrPanic(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
421}
422
423fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
424 var n: usize = 0;
425 while (n < len) : (n += 1) {
426 @ptrCast([*]u8, array.?)[n] += 1;
427 }
428}
429
430test "*usize to *void" {
431 var i = usize(0);
432 var v = @ptrCast(*void, &i);
433 v.* = {};
434}
435
436test "compile time int to ptr of function" {
437 foobar(FUNCTION_CONSTANT);
438}
439
440pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
441pub const PFN_void = extern fn (*c_void) void;
442
443fn foobar(func: PFN_void) void {
444 std.debug.assertOrPanic(@ptrToInt(func) == maxInt(usize));
445}
446
447test "implicit ptr to *c_void" {
448 var a: u32 = 1;
449 var ptr: *c_void = &a;
450 var b: *u32 = @ptrCast(*u32, ptr);
451 assertOrPanic(b.* == 1);
452 var ptr2: ?*c_void = &a;
453 var c: *u32 = @ptrCast(*u32, ptr2.?);
454 assertOrPanic(c.* == 1);
455}
456
457test "@intCast to comptime_int" {
458 assertOrPanic(@intCast(comptime_int, 0) == 0);
459}
460
461test "implicit cast comptime numbers to any type when the value fits" {
462 const a: u64 = 255;
463 var b: u8 = a;
464 assertOrPanic(b == 255);
465}
466
467test "@intToEnum passed a comptime_int to an enum with one item" {
468 const E = enum {
469 A,
470 };
471 const x = @intToEnum(E, 0);
472 assertOrPanic(x == E.A);
473}
test/stage1/behavior/const_slice_child.zig created+45
......@@ -0,0 +1,45 @@
1const debug = @import("std").debug;
2const assertOrPanic = debug.assertOrPanic;
3
4var argv: [*]const [*]const u8 = undefined;
5
6test "const slice child" {
7 const strs = ([][*]const u8){
8 c"one",
9 c"two",
10 c"three",
11 };
12 // TODO this should implicitly cast
13 argv = @ptrCast([*]const [*]const u8, &strs);
14 bar(strs.len);
15}
16
17fn foo(args: [][]const u8) void {
18 assertOrPanic(args.len == 3);
19 assertOrPanic(streql(args[0], "one"));
20 assertOrPanic(streql(args[1], "two"));
21 assertOrPanic(streql(args[2], "three"));
22}
23
24fn bar(argc: usize) void {
25 const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable;
26 for (args) |_, i| {
27 const ptr = argv[i];
28 args[i] = ptr[0..strlen(ptr)];
29 }
30 foo(args);
31}
32
33fn strlen(ptr: [*]const u8) usize {
34 var count: usize = 0;
35 while (ptr[count] != 0) : (count += 1) {}
36 return count;
37}
38
39fn streql(a: []const u8, b: []const u8) bool {
40 if (a.len != b.len) return false;
41 for (a) |item, index| {
42 if (b[index] != item) return false;
43 }
44 return true;
45}
test/stage1/behavior/coroutine_await_struct.zig created+47
......@@ -0,0 +1,47 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assertOrPanic = std.debug.assertOrPanic;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: promise = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 var da = std.heap.DirectAllocator.init();
14 defer da.deinit();
15
16 await_seq('a');
17 const p = async<&da.allocator> await_amain() catch unreachable;
18 await_seq('f');
19 resume await_a_promise;
20 await_seq('i');
21 assertOrPanic(await_final_result.x == 1234);
22 assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi"));
23}
24async fn await_amain() void {
25 await_seq('b');
26 const p = async await_another() catch unreachable;
27 await_seq('e');
28 await_final_result = await p;
29 await_seq('h');
30}
31async fn await_another() Foo {
32 await_seq('c');
33 suspend {
34 await_seq('d');
35 await_a_promise = @handle();
36 }
37 await_seq('g');
38 return Foo{ .x = 1234 };
39}
40
41var await_points = []u8{0} ** "abcdefghi".len;
42var await_seq_index: usize = 0;
43
44fn await_seq(c: u8) void {
45 await_points[await_seq_index] = c;
46 await_seq_index += 1;
47}
test/stage1/behavior/coroutines.zig created+258
......@@ -0,0 +1,258 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assertOrPanic = std.debug.assertOrPanic;
4
5var x: i32 = 1;
6
7test "create a coroutine and cancel it" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = try async<&da.allocator> simpleAsyncFn();
12 comptime assertOrPanic(@typeOf(p) == promise->void);
13 cancel p;
14 assertOrPanic(x == 2);
15}
16async fn simpleAsyncFn() void {
17 x += 1;
18 suspend;
19 x += 1;
20}
21
22test "coroutine suspend, resume, cancel" {
23 var da = std.heap.DirectAllocator.init();
24 defer da.deinit();
25
26 seq('a');
27 const p = try async<&da.allocator> testAsyncSeq();
28 seq('c');
29 resume p;
30 seq('f');
31 cancel p;
32 seq('g');
33
34 assertOrPanic(std.mem.eql(u8, points, "abcdefg"));
35}
36async fn testAsyncSeq() void {
37 defer seq('e');
38
39 seq('b');
40 suspend;
41 seq('d');
42}
43var points = []u8{0} ** "abcdefg".len;
44var index: usize = 0;
45
46fn seq(c: u8) void {
47 points[index] = c;
48 index += 1;
49}
50
51test "coroutine suspend with block" {
52 var da = std.heap.DirectAllocator.init();
53 defer da.deinit();
54
55 const p = try async<&da.allocator> testSuspendBlock();
56 std.debug.assertOrPanic(!result);
57 resume a_promise;
58 std.debug.assertOrPanic(result);
59 cancel p;
60}
61
62var a_promise: promise = undefined;
63var result = false;
64async fn testSuspendBlock() void {
65 suspend {
66 comptime assertOrPanic(@typeOf(@handle()) == promise->void);
67 a_promise = @handle();
68 }
69
70 //Test to make sure that @handle() works as advertised (issue #1296)
71 //var our_handle: promise = @handle();
72 assertOrPanic(a_promise == @handle());
73
74 result = true;
75}
76
77var await_a_promise: promise = undefined;
78var await_final_result: i32 = 0;
79
80test "coroutine await" {
81 var da = std.heap.DirectAllocator.init();
82 defer da.deinit();
83
84 await_seq('a');
85 const p = async<&da.allocator> await_amain() catch unreachable;
86 await_seq('f');
87 resume await_a_promise;
88 await_seq('i');
89 assertOrPanic(await_final_result == 1234);
90 assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi"));
91}
92async fn await_amain() void {
93 await_seq('b');
94 const p = async await_another() catch unreachable;
95 await_seq('e');
96 await_final_result = await p;
97 await_seq('h');
98}
99async fn await_another() i32 {
100 await_seq('c');
101 suspend {
102 await_seq('d');
103 await_a_promise = @handle();
104 }
105 await_seq('g');
106 return 1234;
107}
108
109var await_points = []u8{0} ** "abcdefghi".len;
110var await_seq_index: usize = 0;
111
112fn await_seq(c: u8) void {
113 await_points[await_seq_index] = c;
114 await_seq_index += 1;
115}
116
117var early_final_result: i32 = 0;
118
119test "coroutine await early return" {
120 var da = std.heap.DirectAllocator.init();
121 defer da.deinit();
122
123 early_seq('a');
124 const p = async<&da.allocator> early_amain() catch @panic("out of memory");
125 early_seq('f');
126 assertOrPanic(early_final_result == 1234);
127 assertOrPanic(std.mem.eql(u8, early_points, "abcdef"));
128}
129async fn early_amain() void {
130 early_seq('b');
131 const p = async early_another() catch @panic("out of memory");
132 early_seq('d');
133 early_final_result = await p;
134 early_seq('e');
135}
136async fn early_another() i32 {
137 early_seq('c');
138 return 1234;
139}
140
141var early_points = []u8{0} ** "abcdef".len;
142var early_seq_index: usize = 0;
143
144fn early_seq(c: u8) void {
145 early_points[early_seq_index] = c;
146 early_seq_index += 1;
147}
148
149test "coro allocation failure" {
150 var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);
151 if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) {
152 @panic("expected allocation failure");
153 } else |err| switch (err) {
154 error.OutOfMemory => {},
155 }
156}
157async fn asyncFuncThatNeverGetsRun() void {
158 @panic("coro frame allocation should fail");
159}
160
161test "async function with dot syntax" {
162 const S = struct {
163 var y: i32 = 1;
164 async fn foo() void {
165 y += 1;
166 suspend;
167 }
168 };
169 var da = std.heap.DirectAllocator.init();
170 defer da.deinit();
171 const p = try async<&da.allocator> S.foo();
172 cancel p;
173 assertOrPanic(S.y == 2);
174}
175
176test "async fn pointer in a struct field" {
177 var data: i32 = 1;
178 const Foo = struct {
179 bar: async<*std.mem.Allocator> fn (*i32) void,
180 };
181 var foo = Foo{ .bar = simpleAsyncFn2 };
182 var da = std.heap.DirectAllocator.init();
183 defer da.deinit();
184 const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
185 assertOrPanic(data == 2);
186 cancel p;
187 assertOrPanic(data == 4);
188}
189async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
190 defer y.* += 2;
191 y.* += 1;
192 suspend;
193}
194
195test "async fn with inferred error set" {
196 var da = std.heap.DirectAllocator.init();
197 defer da.deinit();
198 const p = (async<&da.allocator> failing()) catch unreachable;
199 resume p;
200 cancel p;
201}
202
203async fn failing() !void {
204 suspend;
205 return error.Fail;
206}
207
208test "error return trace across suspend points - early return" {
209 const p = nonFailing();
210 resume p;
211 var da = std.heap.DirectAllocator.init();
212 defer da.deinit();
213 const p2 = try async<&da.allocator> printTrace(p);
214 cancel p2;
215}
216
217test "error return trace across suspend points - async return" {
218 const p = nonFailing();
219 const p2 = try async<std.debug.global_allocator> printTrace(p);
220 resume p;
221 cancel p2;
222}
223
224fn nonFailing() (promise->anyerror!void) {
225 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
226}
227async fn suspendThenFail() anyerror!void {
228 suspend;
229 return error.Fail;
230}
231async fn printTrace(p: promise->(anyerror!void)) void {
232 (await p) catch |e| {
233 std.debug.assertOrPanic(e == error.Fail);
234 if (@errorReturnTrace()) |trace| {
235 assertOrPanic(trace.index == 1);
236 } else switch (builtin.mode) {
237 builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
238 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
239 }
240 };
241}
242
243test "break from suspend" {
244 var buf: [500]u8 = undefined;
245 var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
246 var my_result: i32 = 1;
247 const p = try async<a> testBreakFromSuspend(&my_result);
248 cancel p;
249 std.debug.assertOrPanic(my_result == 2);
250}
251async fn testBreakFromSuspend(my_result: *i32) void {
252 suspend {
253 resume @handle();
254 }
255 my_result.* += 1;
256 suspend;
257 my_result.* += 1;
258}
test/stage1/behavior/defer.zig created+78
......@@ -0,0 +1,78 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3var result: [3]u8 = undefined;
4var index: usize = undefined;
5
6fn runSomeErrorDefers(x: bool) !bool {
7 index = 0;
8 defer {
9 result[index] = 'a';
10 index += 1;
11 }
12 errdefer {
13 result[index] = 'b';
14 index += 1;
15 }
16 defer {
17 result[index] = 'c';
18 index += 1;
19 }
20 return if (x) x else error.FalseNotAllowed;
21}
22
23test "mixing normal and error defers" {
24 assertOrPanic(runSomeErrorDefers(true) catch unreachable);
25 assertOrPanic(result[0] == 'c');
26 assertOrPanic(result[1] == 'a');
27
28 const ok = runSomeErrorDefers(false) catch |err| x: {
29 assertOrPanic(err == error.FalseNotAllowed);
30 break :x true;
31 };
32 assertOrPanic(ok);
33 assertOrPanic(result[0] == 'c');
34 assertOrPanic(result[1] == 'b');
35 assertOrPanic(result[2] == 'a');
36}
37
38test "break and continue inside loop inside defer expression" {
39 testBreakContInDefer(10);
40 comptime testBreakContInDefer(10);
41}
42
43fn testBreakContInDefer(x: usize) void {
44 defer {
45 var i: usize = 0;
46 while (i < x) : (i += 1) {
47 if (i < 5) continue;
48 if (i == 5) break;
49 }
50 assertOrPanic(i == 5);
51 }
52}
53
54test "defer and labeled break" {
55 var i = usize(0);
56
57 blk: {
58 defer i += 1;
59 break :blk;
60 }
61
62 assertOrPanic(i == 1);
63}
64
65test "errdefer does not apply to fn inside fn" {
66 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assertOrPanic(e == error.Bad);
67}
68
69fn testNestedFnErrDefer() anyerror!void {
70 var a: i32 = 0;
71 errdefer a += 1;
72 const S = struct {
73 fn baz() anyerror {
74 return error.Bad;
75 }
76 };
77 return S.baz();
78}
test/stage1/behavior/enum.zig created+894
......@@ -0,0 +1,894 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4test "enum type" {
5 const foo1 = Foo{ .One = 13 };
6 const foo2 = Foo{
7 .Two = Point{
8 .x = 1234,
9 .y = 5678,
10 },
11 };
12 const bar = Bar.B;
13
14 assertOrPanic(bar == Bar.B);
15 assertOrPanic(@memberCount(Foo) == 3);
16 assertOrPanic(@memberCount(Bar) == 4);
17 assertOrPanic(@sizeOf(Foo) == @sizeOf(FooNoVoid));
18 assertOrPanic(@sizeOf(Bar) == 1);
19}
20
21test "enum as return value" {
22 switch (returnAnInt(13)) {
23 Foo.One => |value| assertOrPanic(value == 13),
24 else => unreachable,
25 }
26}
27
28const Point = struct {
29 x: u64,
30 y: u64,
31};
32const Foo = union(enum) {
33 One: i32,
34 Two: Point,
35 Three: void,
36};
37const FooNoVoid = union(enum) {
38 One: i32,
39 Two: Point,
40};
41const Bar = enum {
42 A,
43 B,
44 C,
45 D,
46};
47
48fn returnAnInt(x: i32) Foo {
49 return Foo{ .One = x };
50}
51
52test "constant enum with payload" {
53 var empty = AnEnumWithPayload{ .Empty = {} };
54 var full = AnEnumWithPayload{ .Full = 13 };
55 shouldBeEmpty(empty);
56 shouldBeNotEmpty(full);
57}
58
59fn shouldBeEmpty(x: AnEnumWithPayload) void {
60 switch (x) {
61 AnEnumWithPayload.Empty => {},
62 else => unreachable,
63 }
64}
65
66fn shouldBeNotEmpty(x: AnEnumWithPayload) void {
67 switch (x) {
68 AnEnumWithPayload.Empty => unreachable,
69 else => {},
70 }
71}
72
73const AnEnumWithPayload = union(enum) {
74 Empty: void,
75 Full: i32,
76};
77
78const Number = enum {
79 Zero,
80 One,
81 Two,
82 Three,
83 Four,
84};
85
86test "enum to int" {
87 shouldEqual(Number.Zero, 0);
88 shouldEqual(Number.One, 1);
89 shouldEqual(Number.Two, 2);
90 shouldEqual(Number.Three, 3);
91 shouldEqual(Number.Four, 4);
92}
93
94fn shouldEqual(n: Number, expected: u3) void {
95 assertOrPanic(@enumToInt(n) == expected);
96}
97
98test "int to enum" {
99 testIntToEnumEval(3);
100}
101fn testIntToEnumEval(x: i32) void {
102 assertOrPanic(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103}
104const IntToEnumNumber = enum {
105 Zero,
106 One,
107 Two,
108 Three,
109 Four,
110};
111
112test "@tagName" {
113 assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114 comptime assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
115}
116
117fn testEnumTagNameBare(n: BareNumber) []const u8 {
118 return @tagName(n);
119}
120
121const BareNumber = enum {
122 One,
123 Two,
124 Three,
125};
126
127test "enum alignment" {
128 comptime {
129 assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
130 assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf(u64));
131 }
132}
133
134const AlignTestEnum = union(enum) {
135 A: [9]u8,
136 B: u64,
137};
138
139const ValueCount1 = enum {
140 I0,
141};
142const ValueCount2 = enum {
143 I0,
144 I1,
145};
146const ValueCount256 = enum {
147 I0,
148 I1,
149 I2,
150 I3,
151 I4,
152 I5,
153 I6,
154 I7,
155 I8,
156 I9,
157 I10,
158 I11,
159 I12,
160 I13,
161 I14,
162 I15,
163 I16,
164 I17,
165 I18,
166 I19,
167 I20,
168 I21,
169 I22,
170 I23,
171 I24,
172 I25,
173 I26,
174 I27,
175 I28,
176 I29,
177 I30,
178 I31,
179 I32,
180 I33,
181 I34,
182 I35,
183 I36,
184 I37,
185 I38,
186 I39,
187 I40,
188 I41,
189 I42,
190 I43,
191 I44,
192 I45,
193 I46,
194 I47,
195 I48,
196 I49,
197 I50,
198 I51,
199 I52,
200 I53,
201 I54,
202 I55,
203 I56,
204 I57,
205 I58,
206 I59,
207 I60,
208 I61,
209 I62,
210 I63,
211 I64,
212 I65,
213 I66,
214 I67,
215 I68,
216 I69,
217 I70,
218 I71,
219 I72,
220 I73,
221 I74,
222 I75,
223 I76,
224 I77,
225 I78,
226 I79,
227 I80,
228 I81,
229 I82,
230 I83,
231 I84,
232 I85,
233 I86,
234 I87,
235 I88,
236 I89,
237 I90,
238 I91,
239 I92,
240 I93,
241 I94,
242 I95,
243 I96,
244 I97,
245 I98,
246 I99,
247 I100,
248 I101,
249 I102,
250 I103,
251 I104,
252 I105,
253 I106,
254 I107,
255 I108,
256 I109,
257 I110,
258 I111,
259 I112,
260 I113,
261 I114,
262 I115,
263 I116,
264 I117,
265 I118,
266 I119,
267 I120,
268 I121,
269 I122,
270 I123,
271 I124,
272 I125,
273 I126,
274 I127,
275 I128,
276 I129,
277 I130,
278 I131,
279 I132,
280 I133,
281 I134,
282 I135,
283 I136,
284 I137,
285 I138,
286 I139,
287 I140,
288 I141,
289 I142,
290 I143,
291 I144,
292 I145,
293 I146,
294 I147,
295 I148,
296 I149,
297 I150,
298 I151,
299 I152,
300 I153,
301 I154,
302 I155,
303 I156,
304 I157,
305 I158,
306 I159,
307 I160,
308 I161,
309 I162,
310 I163,
311 I164,
312 I165,
313 I166,
314 I167,
315 I168,
316 I169,
317 I170,
318 I171,
319 I172,
320 I173,
321 I174,
322 I175,
323 I176,
324 I177,
325 I178,
326 I179,
327 I180,
328 I181,
329 I182,
330 I183,
331 I184,
332 I185,
333 I186,
334 I187,
335 I188,
336 I189,
337 I190,
338 I191,
339 I192,
340 I193,
341 I194,
342 I195,
343 I196,
344 I197,
345 I198,
346 I199,
347 I200,
348 I201,
349 I202,
350 I203,
351 I204,
352 I205,
353 I206,
354 I207,
355 I208,
356 I209,
357 I210,
358 I211,
359 I212,
360 I213,
361 I214,
362 I215,
363 I216,
364 I217,
365 I218,
366 I219,
367 I220,
368 I221,
369 I222,
370 I223,
371 I224,
372 I225,
373 I226,
374 I227,
375 I228,
376 I229,
377 I230,
378 I231,
379 I232,
380 I233,
381 I234,
382 I235,
383 I236,
384 I237,
385 I238,
386 I239,
387 I240,
388 I241,
389 I242,
390 I243,
391 I244,
392 I245,
393 I246,
394 I247,
395 I248,
396 I249,
397 I250,
398 I251,
399 I252,
400 I253,
401 I254,
402 I255,
403};
404const ValueCount257 = enum {
405 I0,
406 I1,
407 I2,
408 I3,
409 I4,
410 I5,
411 I6,
412 I7,
413 I8,
414 I9,
415 I10,
416 I11,
417 I12,
418 I13,
419 I14,
420 I15,
421 I16,
422 I17,
423 I18,
424 I19,
425 I20,
426 I21,
427 I22,
428 I23,
429 I24,
430 I25,
431 I26,
432 I27,
433 I28,
434 I29,
435 I30,
436 I31,
437 I32,
438 I33,
439 I34,
440 I35,
441 I36,
442 I37,
443 I38,
444 I39,
445 I40,
446 I41,
447 I42,
448 I43,
449 I44,
450 I45,
451 I46,
452 I47,
453 I48,
454 I49,
455 I50,
456 I51,
457 I52,
458 I53,
459 I54,
460 I55,
461 I56,
462 I57,
463 I58,
464 I59,
465 I60,
466 I61,
467 I62,
468 I63,
469 I64,
470 I65,
471 I66,
472 I67,
473 I68,
474 I69,
475 I70,
476 I71,
477 I72,
478 I73,
479 I74,
480 I75,
481 I76,
482 I77,
483 I78,
484 I79,
485 I80,
486 I81,
487 I82,
488 I83,
489 I84,
490 I85,
491 I86,
492 I87,
493 I88,
494 I89,
495 I90,
496 I91,
497 I92,
498 I93,
499 I94,
500 I95,
501 I96,
502 I97,
503 I98,
504 I99,
505 I100,
506 I101,
507 I102,
508 I103,
509 I104,
510 I105,
511 I106,
512 I107,
513 I108,
514 I109,
515 I110,
516 I111,
517 I112,
518 I113,
519 I114,
520 I115,
521 I116,
522 I117,
523 I118,
524 I119,
525 I120,
526 I121,
527 I122,
528 I123,
529 I124,
530 I125,
531 I126,
532 I127,
533 I128,
534 I129,
535 I130,
536 I131,
537 I132,
538 I133,
539 I134,
540 I135,
541 I136,
542 I137,
543 I138,
544 I139,
545 I140,
546 I141,
547 I142,
548 I143,
549 I144,
550 I145,
551 I146,
552 I147,
553 I148,
554 I149,
555 I150,
556 I151,
557 I152,
558 I153,
559 I154,
560 I155,
561 I156,
562 I157,
563 I158,
564 I159,
565 I160,
566 I161,
567 I162,
568 I163,
569 I164,
570 I165,
571 I166,
572 I167,
573 I168,
574 I169,
575 I170,
576 I171,
577 I172,
578 I173,
579 I174,
580 I175,
581 I176,
582 I177,
583 I178,
584 I179,
585 I180,
586 I181,
587 I182,
588 I183,
589 I184,
590 I185,
591 I186,
592 I187,
593 I188,
594 I189,
595 I190,
596 I191,
597 I192,
598 I193,
599 I194,
600 I195,
601 I196,
602 I197,
603 I198,
604 I199,
605 I200,
606 I201,
607 I202,
608 I203,
609 I204,
610 I205,
611 I206,
612 I207,
613 I208,
614 I209,
615 I210,
616 I211,
617 I212,
618 I213,
619 I214,
620 I215,
621 I216,
622 I217,
623 I218,
624 I219,
625 I220,
626 I221,
627 I222,
628 I223,
629 I224,
630 I225,
631 I226,
632 I227,
633 I228,
634 I229,
635 I230,
636 I231,
637 I232,
638 I233,
639 I234,
640 I235,
641 I236,
642 I237,
643 I238,
644 I239,
645 I240,
646 I241,
647 I242,
648 I243,
649 I244,
650 I245,
651 I246,
652 I247,
653 I248,
654 I249,
655 I250,
656 I251,
657 I252,
658 I253,
659 I254,
660 I255,
661 I256,
662};
663
664test "enum sizes" {
665 comptime {
666 assertOrPanic(@sizeOf(ValueCount1) == 0);
667 assertOrPanic(@sizeOf(ValueCount2) == 1);
668 assertOrPanic(@sizeOf(ValueCount256) == 1);
669 assertOrPanic(@sizeOf(ValueCount257) == 2);
670 }
671}
672
673const Small2 = enum(u2) {
674 One,
675 Two,
676};
677const Small = enum(u2) {
678 One,
679 Two,
680 Three,
681 Four,
682};
683
684test "set enum tag type" {
685 {
686 var x = Small.One;
687 x = Small.Two;
688 comptime assertOrPanic(@TagType(Small) == u2);
689 }
690 {
691 var x = Small2.One;
692 x = Small2.Two;
693 comptime assertOrPanic(@TagType(Small2) == u2);
694 }
695}
696
697const A = enum(u3) {
698 One,
699 Two,
700 Three,
701 Four,
702 One2,
703 Two2,
704 Three2,
705 Four2,
706};
707
708const B = enum(u3) {
709 One3,
710 Two3,
711 Three3,
712 Four3,
713 One23,
714 Two23,
715 Three23,
716 Four23,
717};
718
719const C = enum(u2) {
720 One4,
721 Two4,
722 Three4,
723 Four4,
724};
725
726const BitFieldOfEnums = packed struct {
727 a: A,
728 b: B,
729 c: C,
730};
731
732const bit_field_1 = BitFieldOfEnums{
733 .a = A.Two,
734 .b = B.Three3,
735 .c = C.Four4,
736};
737
738test "bit field access with enum fields" {
739 var data = bit_field_1;
740 assertOrPanic(getA(&data) == A.Two);
741 assertOrPanic(getB(&data) == B.Three3);
742 assertOrPanic(getC(&data) == C.Four4);
743 comptime assertOrPanic(@sizeOf(BitFieldOfEnums) == 1);
744
745 data.b = B.Four3;
746 assertOrPanic(data.b == B.Four3);
747
748 data.a = A.Three;
749 assertOrPanic(data.a == A.Three);
750 assertOrPanic(data.b == B.Four3);
751}
752
753fn getA(data: *const BitFieldOfEnums) A {
754 return data.a;
755}
756
757fn getB(data: *const BitFieldOfEnums) B {
758 return data.b;
759}
760
761fn getC(data: *const BitFieldOfEnums) C {
762 return data.c;
763}
764
765test "casting enum to its tag type" {
766 testCastEnumToTagType(Small2.Two);
767 comptime testCastEnumToTagType(Small2.Two);
768}
769
770fn testCastEnumToTagType(value: Small2) void {
771 assertOrPanic(@enumToInt(value) == 1);
772}
773
774const MultipleChoice = enum(u32) {
775 A = 20,
776 B = 40,
777 C = 60,
778 D = 1000,
779};
780
781test "enum with specified tag values" {
782 testEnumWithSpecifiedTagValues(MultipleChoice.C);
783 comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
784}
785
786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 assertOrPanic(@enumToInt(x) == 60);
788 assertOrPanic(1234 == switch (x) {
789 MultipleChoice.A => 1,
790 MultipleChoice.B => 2,
791 MultipleChoice.C => u32(1234),
792 MultipleChoice.D => 4,
793 });
794}
795
796const MultipleChoice2 = enum(u32) {
797 Unspecified1,
798 A = 20,
799 Unspecified2,
800 B = 40,
801 Unspecified3,
802 C = 60,
803 Unspecified4,
804 D = 1000,
805 Unspecified5,
806};
807
808test "enum with specified and unspecified tag values" {
809 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
810 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
811}
812
813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 assertOrPanic(@enumToInt(x) == 1000);
815 assertOrPanic(1234 == switch (x) {
816 MultipleChoice2.A => 1,
817 MultipleChoice2.B => 2,
818 MultipleChoice2.C => 3,
819 MultipleChoice2.D => u32(1234),
820 MultipleChoice2.Unspecified1 => 5,
821 MultipleChoice2.Unspecified2 => 6,
822 MultipleChoice2.Unspecified3 => 7,
823 MultipleChoice2.Unspecified4 => 8,
824 MultipleChoice2.Unspecified5 => 9,
825 });
826}
827
828test "cast integer literal to enum" {
829 assertOrPanic(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assertOrPanic(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831}
832
833const EnumWithOneMember = enum {
834 Eof,
835};
836
837fn doALoopThing(id: EnumWithOneMember) void {
838 while (true) {
839 if (id == EnumWithOneMember.Eof) {
840 break;
841 }
842 @compileError("above if condition should be comptime");
843 }
844}
845
846test "comparison operator on enum with one member is comptime known" {
847 doALoopThing(EnumWithOneMember.Eof);
848}
849
850const State = enum {
851 Start,
852};
853test "switch on enum with one member is comptime known" {
854 var state = State.Start;
855 switch (state) {
856 State.Start => return,
857 }
858 @compileError("analysis should not reach here");
859}
860
861const EnumWithTagValues = enum(u4) {
862 A = 1 << 0,
863 B = 1 << 1,
864 C = 1 << 2,
865 D = 1 << 3,
866};
867test "enum with tag values don't require parens" {
868 assertOrPanic(@enumToInt(EnumWithTagValues.C) == 0b0100);
869}
870
871test "enum with 1 field but explicit tag type should still have the tag type" {
872 const Enum = enum(u8) {
873 B = 2,
874 };
875 comptime @import("std").debug.assertOrPanic(@sizeOf(Enum) == @sizeOf(u8));
876}
877
878test "empty extern enum with members" {
879 const E = extern enum {
880 A,
881 B,
882 C,
883 };
884 assertOrPanic(@sizeOf(E) == @sizeOf(c_int));
885}
886
887test "tag name with assigned enum values" {
888 const LocalFoo = enum {
889 A = 1,
890 B = 0,
891 };
892 var b = LocalFoo.B;
893 assertOrPanic(mem.eql(u8, @tagName(b), "B"));
894}
test/stage1/behavior/enum_with_members.zig created+27
......@@ -0,0 +1,27 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3const fmt = @import("std").fmt;
4
5const ET = union(enum) {
6 SINT: i32,
7 UINT: u32,
8
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
13 };
14 }
15};
16
17test "enum with members" {
18 const a = ET{ .SINT = -42 };
19 const b = ET{ .UINT = 42 };
20 var buf: [20]u8 = undefined;
21
22 assertOrPanic((a.print(buf[0..]) catch unreachable) == 3);
23 assertOrPanic(mem.eql(u8, buf[0..3], "-42"));
24
25 assertOrPanic((b.print(buf[0..]) catch unreachable) == 2);
26 assertOrPanic(mem.eql(u8, buf[0..2], "42"));
27}
test/stage1/behavior/error.zig created+332
......@@ -0,0 +1,332 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const assertError = std.debug.assertError;
4const mem = std.mem;
5const builtin = @import("builtin");
6
7pub fn foo() anyerror!i32 {
8 const x = try bar();
9 return x + 1;
10}
11
12pub fn bar() anyerror!i32 {
13 return 13;
14}
15
16pub fn baz() anyerror!i32 {
17 const y = foo() catch 1234;
18 return y + 1;
19}
20
21test "error wrapping" {
22 assertOrPanic((baz() catch unreachable) == 15);
23}
24
25fn gimmeItBroke() []const u8 {
26 return @errorName(error.ItBroke);
27}
28
29test "@errorName" {
30 assertOrPanic(mem.eql(u8, @errorName(error.AnError), "AnError"));
31 assertOrPanic(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
32}
33
34test "error values" {
35 const a = @errorToInt(error.err1);
36 const b = @errorToInt(error.err2);
37 assertOrPanic(a != b);
38}
39
40test "redefinition of error values allowed" {
41 shouldBeNotEqual(error.AnError, error.SecondError);
42}
43fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
44 if (a == b) unreachable;
45}
46
47test "error binary operator" {
48 const a = errBinaryOperatorG(true) catch 3;
49 const b = errBinaryOperatorG(false) catch 3;
50 assertOrPanic(a == 3);
51 assertOrPanic(b == 10);
52}
53fn errBinaryOperatorG(x: bool) anyerror!isize {
54 return if (x) error.ItBroke else isize(10);
55}
56
57test "unwrap simple value from error" {
58 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
59 assertOrPanic(i == 13);
60}
61fn unwrapSimpleValueFromErrorDo() anyerror!isize {
62 return 13;
63}
64
65test "error return in assignment" {
66 doErrReturnInAssignment() catch unreachable;
67}
68
69fn doErrReturnInAssignment() anyerror!void {
70 var x: i32 = undefined;
71 x = try makeANonErr();
72}
73
74fn makeANonErr() anyerror!i32 {
75 return 1;
76}
77
78test "error union type " {
79 testErrorUnionType();
80 comptime testErrorUnionType();
81}
82
83fn testErrorUnionType() void {
84 const x: anyerror!i32 = 1234;
85 if (x) |value| assertOrPanic(value == 1234) else |_| unreachable;
86 assertOrPanic(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
87 assertOrPanic(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
88 assertOrPanic(@typeOf(x).ErrorSet == anyerror);
89}
90
91test "error set type" {
92 testErrorSetType();
93 comptime testErrorSetType();
94}
95
96const MyErrSet = error{
97 OutOfMemory,
98 FileNotFound,
99};
100
101fn testErrorSetType() void {
102 assertOrPanic(@memberCount(MyErrSet) == 2);
103
104 const a: MyErrSet!i32 = 5678;
105 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
106
107 if (a) |value| assertOrPanic(value == 5678) else |err| switch (err) {
108 error.OutOfMemory => unreachable,
109 error.FileNotFound => unreachable,
110 }
111}
112
113test "explicit error set cast" {
114 testExplicitErrorSetCast(Set1.A);
115 comptime testExplicitErrorSetCast(Set1.A);
116}
117
118const Set1 = error{
119 A,
120 B,
121};
122const Set2 = error{
123 A,
124 C,
125};
126
127fn testExplicitErrorSetCast(set1: Set1) void {
128 var x = @errSetCast(Set2, set1);
129 var y = @errSetCast(Set1, x);
130 assertOrPanic(y == error.A);
131}
132
133test "comptime test error for empty error set" {
134 testComptimeTestErrorEmptySet(1234);
135 comptime testComptimeTestErrorEmptySet(1234);
136}
137
138const EmptyErrorSet = error{};
139
140fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
141 if (x) |v| assertOrPanic(v == 1234) else |err| @compileError("bad");
142}
143
144test "syntax: optional operator in front of error union operator" {
145 comptime {
146 assertOrPanic(?(anyerror!i32) == ?(anyerror!i32));
147 }
148}
149
150test "comptime err to int of error set with only 1 possible value" {
151 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
153}
154fn testErrToIntWithOnePossibleValue(
155 x: error{A},
156 comptime value: u32,
157) void {
158 if (@errorToInt(x) != value) {
159 @compileError("bad");
160 }
161}
162
163test "error union peer type resolution" {
164 testErrorUnionPeerTypeResolution(1);
165}
166
167fn testErrorUnionPeerTypeResolution(x: i32) void {
168 const y = switch (x) {
169 1 => bar_1(),
170 2 => baz_1(),
171 else => quux_1(),
172 };
173 if (y) |_| {
174 @panic("expected error");
175 } else |e| {
176 assertOrPanic(e == error.A);
177 }
178}
179
180fn bar_1() anyerror {
181 return error.A;
182}
183
184fn baz_1() !i32 {
185 return error.B;
186}
187
188fn quux_1() !i32 {
189 return error.C;
190}
191
192test "error: fn returning empty error set can be passed as fn returning any error" {
193 entry();
194 comptime entry();
195}
196
197fn entry() void {
198 foo2(bar2);
199}
200
201fn foo2(f: fn () anyerror!void) void {
202 const x = f();
203}
204
205fn bar2() (error{}!void) {}
206
207test "error: Zero sized error set returned with value payload crash" {
208 _ = foo3(0);
209 _ = comptime foo3(0);
210}
211
212const Error = error{};
213fn foo3(b: usize) Error!usize {
214 return b;
215}
216
217test "error: Infer error set from literals" {
218 _ = nullLiteral("n") catch |err| handleErrors(err);
219 _ = floatLiteral("n") catch |err| handleErrors(err);
220 _ = intLiteral("n") catch |err| handleErrors(err);
221 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
222 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
223 _ = comptime intLiteral("n") catch |err| handleErrors(err);
224}
225
226fn handleErrors(err: var) noreturn {
227 switch (err) {
228 error.T => {},
229 }
230
231 unreachable;
232}
233
234fn nullLiteral(str: []const u8) !?i64 {
235 if (str[0] == 'n') return null;
236
237 return error.T;
238}
239
240fn floatLiteral(str: []const u8) !?f64 {
241 if (str[0] == 'n') return 1.0;
242
243 return error.T;
244}
245
246fn intLiteral(str: []const u8) !?i64 {
247 if (str[0] == 'n') return 1;
248
249 return error.T;
250}
251
252test "nested error union function call in optional unwrap" {
253 const S = struct {
254 const Foo = struct {
255 a: i32,
256 };
257
258 fn errorable() !i32 {
259 var x: Foo = (try getFoo()) orelse return error.Other;
260 return x.a;
261 }
262
263 fn errorable2() !i32 {
264 var x: Foo = (try getFoo2()) orelse return error.Other;
265 return x.a;
266 }
267
268 fn errorable3() !i32 {
269 var x: Foo = (try getFoo3()) orelse return error.Other;
270 return x.a;
271 }
272
273 fn getFoo() anyerror!?Foo {
274 return Foo{ .a = 1234 };
275 }
276
277 fn getFoo2() anyerror!?Foo {
278 return error.Failure;
279 }
280
281 fn getFoo3() anyerror!?Foo {
282 return null;
283 }
284 };
285 assertOrPanic((try S.errorable()) == 1234);
286 assertError(S.errorable2(), error.Failure);
287 assertError(S.errorable3(), error.Other);
288 comptime {
289 assertOrPanic((try S.errorable()) == 1234);
290 assertError(S.errorable2(), error.Failure);
291 assertError(S.errorable3(), error.Other);
292 }
293}
294
295test "widen cast integer payload of error union function call" {
296 const S = struct {
297 fn errorable() !u64 {
298 var x = u64(try number());
299 return x;
300 }
301
302 fn number() anyerror!u32 {
303 return 1234;
304 }
305 };
306 assertOrPanic((try S.errorable()) == 1234);
307}
308
309test "return function call to error set from error union function" {
310 const S = struct {
311 fn errorable() anyerror!i32 {
312 return fail();
313 }
314
315 fn fail() anyerror {
316 return error.Failure;
317 }
318 };
319 assertError(S.errorable(), error.Failure);
320 comptime assertError(S.errorable(), error.Failure);
321}
322
323test "optional error set is the same size as error set" {
324 comptime assertOrPanic(@sizeOf(?anyerror) == @sizeOf(anyerror));
325 const S = struct {
326 fn returnsOptErrSet() ?anyerror {
327 return null;
328 }
329 };
330 assertOrPanic(S.returnsOptErrSet() == null);
331 comptime assertOrPanic(S.returnsOptErrSet() == null);
332}
test/stage1/behavior/eval.zig created+784
......@@ -0,0 +1,784 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4
5test "compile time recursion" {
6 assertOrPanic(some_data.len == 21);
7}
8var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
9fn fibonacci(x: i32) i32 {
10 if (x <= 1) return 1;
11 return fibonacci(x - 1) + fibonacci(x - 2);
12}
13
14fn unwrapAndAddOne(blah: ?i32) i32 {
15 return blah.? + 1;
16}
17const should_be_1235 = unwrapAndAddOne(1234);
18test "static add one" {
19 assertOrPanic(should_be_1235 == 1235);
20}
21
22test "inlined loop" {
23 comptime var i = 0;
24 comptime var sum = 0;
25 inline while (i <= 5) : (i += 1)
26 sum += i;
27 assertOrPanic(sum == 15);
28}
29
30fn gimme1or2(comptime a: bool) i32 {
31 const x: i32 = 1;
32 const y: i32 = 2;
33 comptime var z: i32 = if (a) x else y;
34 return z;
35}
36test "inline variable gets result of const if" {
37 assertOrPanic(gimme1or2(true) == 1);
38 assertOrPanic(gimme1or2(false) == 2);
39}
40
41test "static function evaluation" {
42 assertOrPanic(statically_added_number == 3);
43}
44const statically_added_number = staticAdd(1, 2);
45fn staticAdd(a: i32, b: i32) i32 {
46 return a + b;
47}
48
49test "const expr eval on single expr blocks" {
50 assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
51 comptime assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
52}
53
54fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
55 const literal = 3;
56
57 const result = if (b) b: {
58 break :b literal;
59 } else b: {
60 break :b x;
61 };
62
63 return result;
64}
65
66test "statically initialized list" {
67 assertOrPanic(static_point_list[0].x == 1);
68 assertOrPanic(static_point_list[0].y == 2);
69 assertOrPanic(static_point_list[1].x == 3);
70 assertOrPanic(static_point_list[1].y == 4);
71}
72const Point = struct {
73 x: i32,
74 y: i32,
75};
76const static_point_list = []Point{
77 makePoint(1, 2),
78 makePoint(3, 4),
79};
80fn makePoint(x: i32, y: i32) Point {
81 return Point{
82 .x = x,
83 .y = y,
84 };
85}
86
87test "static eval list init" {
88 assertOrPanic(static_vec3.data[2] == 1.0);
89 assertOrPanic(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
90}
91const static_vec3 = vec3(0.0, 0.0, 1.0);
92pub const Vec3 = struct {
93 data: [3]f32,
94};
95pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
96 return Vec3{ .data = []f32{
97 x,
98 y,
99 z,
100 } };
101}
102
103test "constant expressions" {
104 var array: [array_size]u8 = undefined;
105 assertOrPanic(@sizeOf(@typeOf(array)) == 20);
106}
107const array_size: u8 = 20;
108
109test "constant struct with negation" {
110 assertOrPanic(vertices[0].x == -0.6);
111}
112const Vertex = struct {
113 x: f32,
114 y: f32,
115 r: f32,
116 g: f32,
117 b: f32,
118};
119const vertices = []Vertex{
120 Vertex{
121 .x = -0.6,
122 .y = -0.4,
123 .r = 1.0,
124 .g = 0.0,
125 .b = 0.0,
126 },
127 Vertex{
128 .x = 0.6,
129 .y = -0.4,
130 .r = 0.0,
131 .g = 1.0,
132 .b = 0.0,
133 },
134 Vertex{
135 .x = 0.0,
136 .y = 0.6,
137 .r = 0.0,
138 .g = 0.0,
139 .b = 1.0,
140 },
141};
142
143test "statically initialized struct" {
144 st_init_str_foo.x += 1;
145 assertOrPanic(st_init_str_foo.x == 14);
146}
147const StInitStrFoo = struct {
148 x: i32,
149 y: bool,
150};
151var st_init_str_foo = StInitStrFoo{
152 .x = 13,
153 .y = true,
154};
155
156test "statically initalized array literal" {
157 const y: [4]u8 = st_init_arr_lit_x;
158 assertOrPanic(y[3] == 4);
159}
160const st_init_arr_lit_x = []u8{
161 1,
162 2,
163 3,
164 4,
165};
166
167test "const slice" {
168 comptime {
169 const a = "1234567890";
170 assertOrPanic(a.len == 10);
171 const b = a[1..2];
172 assertOrPanic(b.len == 1);
173 assertOrPanic(b[0] == '2');
174 }
175}
176
177test "try to trick eval with runtime if" {
178 assertOrPanic(testTryToTrickEvalWithRuntimeIf(true) == 10);
179}
180
181fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
182 comptime var i: usize = 0;
183 inline while (i < 10) : (i += 1) {
184 const result = if (b) false else true;
185 }
186 comptime {
187 return i;
188 }
189}
190
191fn max(comptime T: type, a: T, b: T) T {
192 if (T == bool) {
193 return a or b;
194 } else if (a > b) {
195 return a;
196 } else {
197 return b;
198 }
199}
200fn letsTryToCompareBools(a: bool, b: bool) bool {
201 return max(bool, a, b);
202}
203test "inlined block and runtime block phi" {
204 assertOrPanic(letsTryToCompareBools(true, true));
205 assertOrPanic(letsTryToCompareBools(true, false));
206 assertOrPanic(letsTryToCompareBools(false, true));
207 assertOrPanic(!letsTryToCompareBools(false, false));
208
209 comptime {
210 assertOrPanic(letsTryToCompareBools(true, true));
211 assertOrPanic(letsTryToCompareBools(true, false));
212 assertOrPanic(letsTryToCompareBools(false, true));
213 assertOrPanic(!letsTryToCompareBools(false, false));
214 }
215}
216
217const CmdFn = struct {
218 name: []const u8,
219 func: fn (i32) i32,
220};
221
222const cmd_fns = []CmdFn{
223 CmdFn{
224 .name = "one",
225 .func = one,
226 },
227 CmdFn{
228 .name = "two",
229 .func = two,
230 },
231 CmdFn{
232 .name = "three",
233 .func = three,
234 },
235};
236fn one(value: i32) i32 {
237 return value + 1;
238}
239fn two(value: i32) i32 {
240 return value + 2;
241}
242fn three(value: i32) i32 {
243 return value + 3;
244}
245
246fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
247 var result: i32 = start_value;
248 comptime var i = 0;
249 inline while (i < cmd_fns.len) : (i += 1) {
250 if (cmd_fns[i].name[0] == prefix_char) {
251 result = cmd_fns[i].func(result);
252 }
253 }
254 return result;
255}
256
257test "comptime iterate over fn ptr list" {
258 assertOrPanic(performFn('t', 1) == 6);
259 assertOrPanic(performFn('o', 0) == 1);
260 assertOrPanic(performFn('w', 99) == 99);
261}
262
263test "eval @setRuntimeSafety at compile-time" {
264 const result = comptime fnWithSetRuntimeSafety();
265 assertOrPanic(result == 1234);
266}
267
268fn fnWithSetRuntimeSafety() i32 {
269 @setRuntimeSafety(true);
270 return 1234;
271}
272
273test "eval @setFloatMode at compile-time" {
274 const result = comptime fnWithFloatMode();
275 assertOrPanic(result == 1234.0);
276}
277
278fn fnWithFloatMode() f32 {
279 @setFloatMode(builtin.FloatMode.Strict);
280 return 1234.0;
281}
282
283const SimpleStruct = struct {
284 field: i32,
285
286 fn method(self: *const SimpleStruct) i32 {
287 return self.field + 3;
288 }
289};
290
291var simple_struct = SimpleStruct{ .field = 1234 };
292
293const bound_fn = simple_struct.method;
294
295test "call method on bound fn referring to var instance" {
296 assertOrPanic(bound_fn() == 1237);
297}
298
299test "ptr to local array argument at comptime" {
300 comptime {
301 var bytes: [10]u8 = undefined;
302 modifySomeBytes(bytes[0..]);
303 assertOrPanic(bytes[0] == 'a');
304 assertOrPanic(bytes[9] == 'b');
305 }
306}
307
308fn modifySomeBytes(bytes: []u8) void {
309 bytes[0] = 'a';
310 bytes[9] = 'b';
311}
312
313test "comparisons 0 <= uint and 0 > uint should be comptime" {
314 testCompTimeUIntComparisons(1234);
315}
316fn testCompTimeUIntComparisons(x: u32) void {
317 if (!(0 <= x)) {
318 @compileError("this condition should be comptime known");
319 }
320 if (0 > x) {
321 @compileError("this condition should be comptime known");
322 }
323 if (!(x >= 0)) {
324 @compileError("this condition should be comptime known");
325 }
326 if (x < 0) {
327 @compileError("this condition should be comptime known");
328 }
329}
330
331test "const ptr to variable data changes at runtime" {
332 assertOrPanic(foo_ref.name[0] == 'a');
333 foo_ref.name = "b";
334 assertOrPanic(foo_ref.name[0] == 'b');
335}
336
337const Foo = struct {
338 name: []const u8,
339};
340
341var foo_contents = Foo{ .name = "a" };
342const foo_ref = &foo_contents;
343
344test "create global array with for loop" {
345 assertOrPanic(global_array[5] == 5 * 5);
346 assertOrPanic(global_array[9] == 9 * 9);
347}
348
349const global_array = x: {
350 var result: [10]usize = undefined;
351 for (result) |*item, index| {
352 item.* = index * index;
353 }
354 break :x result;
355};
356
357test "compile-time downcast when the bits fit" {
358 comptime {
359 const spartan_count: u16 = 255;
360 const byte = @intCast(u8, spartan_count);
361 assertOrPanic(byte == 255);
362 }
363}
364
365const hi1 = "hi";
366const hi2 = hi1;
367test "const global shares pointer with other same one" {
368 assertEqualPtrs(&hi1[0], &hi2[0]);
369 comptime assertOrPanic(&hi1[0] == &hi2[0]);
370}
371fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
372 assertOrPanic(ptr1 == ptr2);
373}
374
375test "@setEvalBranchQuota" {
376 comptime {
377 // 1001 for the loop and then 1 more for the assertOrPanic fn call
378 @setEvalBranchQuota(1002);
379 var i = 0;
380 var sum = 0;
381 while (i < 1001) : (i += 1) {
382 sum += i;
383 }
384 assertOrPanic(sum == 500500);
385 }
386}
387
388// TODO test "float literal at compile time not lossy" {
389// TODO assertOrPanic(16777216.0 + 1.0 == 16777217.0);
390// TODO assertOrPanic(9007199254740992.0 + 1.0 == 9007199254740993.0);
391// TODO }
392
393test "f32 at compile time is lossy" {
394 assertOrPanic(f32(1 << 24) + 1 == 1 << 24);
395}
396
397test "f64 at compile time is lossy" {
398 assertOrPanic(f64(1 << 53) + 1 == 1 << 53);
399}
400
401test "f128 at compile time is lossy" {
402 assertOrPanic(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
403}
404
405comptime {
406 assertOrPanic(f128(1 << 113) == 10384593717069655257060992658440192);
407}
408
409pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
410 return struct {
411 pub const Node = struct {};
412 };
413}
414
415test "string literal used as comptime slice is memoized" {
416 const a = "link";
417 const b = "link";
418 comptime assertOrPanic(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
419 comptime assertOrPanic(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
420}
421
422test "comptime slice of undefined pointer of length 0" {
423 const slice1 = ([*]i32)(undefined)[0..0];
424 assertOrPanic(slice1.len == 0);
425 const slice2 = ([*]i32)(undefined)[100..100];
426 assertOrPanic(slice2.len == 0);
427}
428
429fn copyWithPartialInline(s: []u32, b: []u8) void {
430 comptime var i: usize = 0;
431 inline while (i < 4) : (i += 1) {
432 s[i] = 0;
433 s[i] |= u32(b[i * 4 + 0]) << 24;
434 s[i] |= u32(b[i * 4 + 1]) << 16;
435 s[i] |= u32(b[i * 4 + 2]) << 8;
436 s[i] |= u32(b[i * 4 + 3]) << 0;
437 }
438}
439
440test "binary math operator in partially inlined function" {
441 var s: [4]u32 = undefined;
442 var b: [16]u8 = undefined;
443
444 for (b) |*r, i|
445 r.* = @intCast(u8, i + 1);
446
447 copyWithPartialInline(s[0..], b[0..]);
448 assertOrPanic(s[0] == 0x1020304);
449 assertOrPanic(s[1] == 0x5060708);
450 assertOrPanic(s[2] == 0x90a0b0c);
451 assertOrPanic(s[3] == 0xd0e0f10);
452}
453
454test "comptime function with the same args is memoized" {
455 comptime {
456 assertOrPanic(MakeType(i32) == MakeType(i32));
457 assertOrPanic(MakeType(i32) != MakeType(f64));
458 }
459}
460
461fn MakeType(comptime T: type) type {
462 return struct {
463 field: T,
464 };
465}
466
467test "comptime function with mutable pointer is not memoized" {
468 comptime {
469 var x: i32 = 1;
470 const ptr = &x;
471 increment(ptr);
472 increment(ptr);
473 assertOrPanic(x == 3);
474 }
475}
476
477fn increment(value: *i32) void {
478 value.* += 1;
479}
480
481fn generateTable(comptime T: type) [1010]T {
482 var res: [1010]T = undefined;
483 var i: usize = 0;
484 while (i < 1010) : (i += 1) {
485 res[i] = @intCast(T, i);
486 }
487 return res;
488}
489
490fn doesAlotT(comptime T: type, value: usize) T {
491 @setEvalBranchQuota(5000);
492 const table = comptime blk: {
493 break :blk generateTable(T);
494 };
495 return table[value];
496}
497
498test "@setEvalBranchQuota at same scope as generic function call" {
499 assertOrPanic(doesAlotT(u32, 2) == 2);
500}
501
502test "comptime slice of slice preserves comptime var" {
503 comptime {
504 var buff: [10]u8 = undefined;
505 buff[0..][0..][0] = 1;
506 assertOrPanic(buff[0..][0..][0] == 1);
507 }
508}
509
510test "comptime slice of pointer preserves comptime var" {
511 comptime {
512 var buff: [10]u8 = undefined;
513 var a = buff[0..].ptr;
514 a[0..1][0] = 1;
515 assertOrPanic(buff[0..][0..][0] == 1);
516 }
517}
518
519const SingleFieldStruct = struct {
520 x: i32,
521
522 fn read_x(self: *const SingleFieldStruct) i32 {
523 return self.x;
524 }
525};
526test "const ptr to comptime mutable data is not memoized" {
527 comptime {
528 var foo = SingleFieldStruct{ .x = 1 };
529 assertOrPanic(foo.read_x() == 1);
530 foo.x = 2;
531 assertOrPanic(foo.read_x() == 2);
532 }
533}
534
535test "array concat of slices gives slice" {
536 comptime {
537 var a: []const u8 = "aoeu";
538 var b: []const u8 = "asdf";
539 const c = a ++ b;
540 assertOrPanic(std.mem.eql(u8, c, "aoeuasdf"));
541 }
542}
543
544test "comptime shlWithOverflow" {
545 const ct_shifted: u64 = comptime amt: {
546 var amt = u64(0);
547 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
548 break :amt amt;
549 };
550
551 const rt_shifted: u64 = amt: {
552 var amt = u64(0);
553 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
554 break :amt amt;
555 };
556
557 assertOrPanic(ct_shifted == rt_shifted);
558}
559
560test "runtime 128 bit integer division" {
561 var a: u128 = 152313999999999991610955792383;
562 var b: u128 = 10000000000000000000;
563 var c = a / b;
564 assertOrPanic(c == 15231399999);
565}
566
567pub const Info = struct {
568 version: u8,
569};
570
571pub const diamond_info = Info{ .version = 0 };
572
573test "comptime modification of const struct field" {
574 comptime {
575 var res = diamond_info;
576 res.version = 1;
577 assertOrPanic(diamond_info.version == 0);
578 assertOrPanic(res.version == 1);
579 }
580}
581
582test "pointer to type" {
583 comptime {
584 var T: type = i32;
585 assertOrPanic(T == i32);
586 var ptr = &T;
587 assertOrPanic(@typeOf(ptr) == *type);
588 ptr.* = f32;
589 assertOrPanic(T == f32);
590 assertOrPanic(*T == *f32);
591 }
592}
593
594test "slice of type" {
595 comptime {
596 var types_array = []type{ i32, f64, type };
597 for (types_array) |T, i| {
598 switch (i) {
599 0 => assertOrPanic(T == i32),
600 1 => assertOrPanic(T == f64),
601 2 => assertOrPanic(T == type),
602 else => unreachable,
603 }
604 }
605 for (types_array[0..]) |T, i| {
606 switch (i) {
607 0 => assertOrPanic(T == i32),
608 1 => assertOrPanic(T == f64),
609 2 => assertOrPanic(T == type),
610 else => unreachable,
611 }
612 }
613 }
614}
615
616const Wrapper = struct {
617 T: type,
618};
619
620fn wrap(comptime T: type) Wrapper {
621 return Wrapper{ .T = T };
622}
623
624test "function which returns struct with type field causes implicit comptime" {
625 const ty = wrap(i32).T;
626 assertOrPanic(ty == i32);
627}
628
629test "call method with comptime pass-by-non-copying-value self parameter" {
630 const S = struct {
631 a: u8,
632
633 fn b(comptime s: @This()) u8 {
634 return s.a;
635 }
636 };
637
638 const s = S{ .a = 2 };
639 var b = s.b();
640 assertOrPanic(b == 2);
641}
642
643test "@tagName of @typeId" {
644 const str = @tagName(@typeId(u8));
645 assertOrPanic(std.mem.eql(u8, str, "Int"));
646}
647
648test "setting backward branch quota just before a generic fn call" {
649 @setEvalBranchQuota(1001);
650 loopNTimes(1001);
651}
652
653fn loopNTimes(comptime n: usize) void {
654 comptime var i = 0;
655 inline while (i < n) : (i += 1) {}
656}
657
658test "variable inside inline loop that has different types on different iterations" {
659 testVarInsideInlineLoop(true, u32(42));
660}
661
662fn testVarInsideInlineLoop(args: ...) void {
663 comptime var i = 0;
664 inline while (i < args.len) : (i += 1) {
665 const x = args[i];
666 if (i == 0) assertOrPanic(x);
667 if (i == 1) assertOrPanic(x == 42);
668 }
669}
670
671test "inline for with same type but different values" {
672 var res: usize = 0;
673 inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| {
674 var a: T = undefined;
675 res += a.len;
676 }
677 assertOrPanic(res == 5);
678}
679
680test "refer to the type of a generic function" {
681 const Func = fn (type) void;
682 const f: Func = doNothingWithType;
683 f(i32);
684}
685
686fn doNothingWithType(comptime T: type) void {}
687
688test "zero extend from u0 to u1" {
689 var zero_u0: u0 = 0;
690 var zero_u1: u1 = zero_u0;
691 assertOrPanic(zero_u1 == 0);
692}
693
694test "bit shift a u1" {
695 var x: u1 = 1;
696 var y = x << 0;
697 assertOrPanic(y == 1);
698}
699
700test "@intCast to a u0" {
701 var x: u8 = 0;
702 var y: u0 = @intCast(u0, x);
703 assertOrPanic(y == 0);
704}
705
706test "@bytesToslice on a packed struct" {
707 const F = packed struct {
708 a: u8,
709 };
710
711 var b = [1]u8{9};
712 var f = @bytesToSlice(F, b);
713 assertOrPanic(f[0].a == 9);
714}
715
716test "comptime pointer cast array and then slice" {
717 const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
718
719 const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
720 const sliceA: []const u8 = ptrA[0..2];
721
722 const ptrB: [*]const u8 = &array;
723 const sliceB: []const u8 = ptrB[0..2];
724
725 assertOrPanic(sliceA[1] == 2);
726 assertOrPanic(sliceB[1] == 2);
727}
728
729test "slice bounds in comptime concatenation" {
730 const bs = comptime blk: {
731 const b = c"11";
732 break :blk b[0..1];
733 };
734 const str = "" ++ bs;
735 assertOrPanic(str.len == 1);
736 assertOrPanic(std.mem.eql(u8, str, "1"));
737
738 const str2 = bs ++ "";
739 assertOrPanic(str2.len == 1);
740 assertOrPanic(std.mem.eql(u8, str2, "1"));
741}
742
743test "comptime bitwise operators" {
744 comptime {
745 assertOrPanic(3 & 1 == 1);
746 assertOrPanic(3 & -1 == 3);
747 assertOrPanic(-3 & -1 == -3);
748 assertOrPanic(3 | -1 == -1);
749 assertOrPanic(-3 | -1 == -1);
750 assertOrPanic(3 ^ -1 == -4);
751 assertOrPanic(-3 ^ -1 == 2);
752 assertOrPanic(~i8(-1) == 0);
753 assertOrPanic(~i128(-1) == 0);
754 assertOrPanic(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
755 assertOrPanic(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
756 assertOrPanic(~u128(0) == 0xffffffffffffffffffffffffffffffff);
757 }
758}
759
760test "*align(1) u16 is the same as *align(1:0:2) u16" {
761 comptime {
762 assertOrPanic(*align(1:0:2) u16 == *align(1) u16);
763 // TODO add parsing support for this syntax
764 //assertOrPanic(*align(:0:2) u16 == *u16);
765 }
766}
767
768test "array concatenation forces comptime" {
769 var a = oneItem(3) ++ oneItem(4);
770 assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 4 }));
771}
772
773test "array multiplication forces comptime" {
774 var a = oneItem(3) ** scalar(2);
775 assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 3 }));
776}
777
778fn oneItem(x: i32) [1]i32 {
779 return []i32{x};
780}
781
782fn scalar(x: u32) u32 {
783 return x;
784}
test/stage1/behavior/field_parent_ptr.zig created+41
......@@ -0,0 +1,41 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "@fieldParentPtr non-first field" {
4 testParentFieldPtr(&foo.c);
5 comptime testParentFieldPtr(&foo.c);
6}
7
8test "@fieldParentPtr first field" {
9 testParentFieldPtrFirst(&foo.a);
10 comptime testParentFieldPtrFirst(&foo.a);
11}
12
13const Foo = struct {
14 a: bool,
15 b: f32,
16 c: i32,
17 d: i32,
18};
19
20const foo = Foo{
21 .a = true,
22 .b = 0.123,
23 .c = 1234,
24 .d = -10,
25};
26
27fn testParentFieldPtr(c: *const i32) void {
28 assertOrPanic(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 assertOrPanic(base == &foo);
32 assertOrPanic(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) void {
36 assertOrPanic(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 assertOrPanic(base == &foo);
40 assertOrPanic(&base.a == a);
41}
test/stage1/behavior/fn.zig created+208
......@@ -0,0 +1,208 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "params" {
4 assertOrPanic(testParamsAdd(22, 11) == 33);
5}
6fn testParamsAdd(a: i32, b: i32) i32 {
7 return a + b;
8}
9
10test "local variables" {
11 testLocVars(2);
12}
13fn testLocVars(b: i32) void {
14 const a: i32 = 1;
15 if (a + b != 3) unreachable;
16}
17
18test "void parameters" {
19 voidFun(1, void{}, 2, {});
20}
21fn voidFun(a: i32, b: void, c: i32, d: void) void {
22 const v = b;
23 const vv: void = if (a == 1) v else {};
24 assertOrPanic(a + c == 3);
25 return vv;
26}
27
28test "mutable local variables" {
29 var zero: i32 = 0;
30 assertOrPanic(zero == 0);
31
32 var i = i32(0);
33 while (i != 3) {
34 i += 1;
35 }
36 assertOrPanic(i == 3);
37}
38
39test "separate block scopes" {
40 {
41 const no_conflict: i32 = 5;
42 assertOrPanic(no_conflict == 5);
43 }
44
45 const c = x: {
46 const no_conflict = i32(10);
47 break :x no_conflict;
48 };
49 assertOrPanic(c == 10);
50}
51
52test "call function with empty string" {
53 acceptsString("");
54}
55
56fn acceptsString(foo: []u8) void {}
57
58fn @"weird function name"() i32 {
59 return 1234;
60}
61test "weird function name" {
62 assertOrPanic(@"weird function name"() == 1234);
63}
64
65test "implicit cast function unreachable return" {
66 wantsFnWithVoid(fnWithUnreachable);
67}
68
69fn wantsFnWithVoid(f: fn () void) void {}
70
71fn fnWithUnreachable() noreturn {
72 unreachable;
73}
74
75test "function pointers" {
76 const fns = []@typeOf(fn1){
77 fn1,
78 fn2,
79 fn3,
80 fn4,
81 };
82 for (fns) |f, i| {
83 assertOrPanic(f() == @intCast(u32, i) + 5);
84 }
85}
86fn fn1() u32 {
87 return 5;
88}
89fn fn2() u32 {
90 return 6;
91}
92fn fn3() u32 {
93 return 7;
94}
95fn fn4() u32 {
96 return 8;
97}
98
99test "inline function call" {
100 assertOrPanic(@inlineCall(add, 3, 9) == 12);
101}
102
103fn add(a: i32, b: i32) i32 {
104 return a + b;
105}
106
107test "number literal as an argument" {
108 numberLiteralArg(3);
109 comptime numberLiteralArg(3);
110}
111
112fn numberLiteralArg(a: var) void {
113 assertOrPanic(a == 3);
114}
115
116test "assign inline fn to const variable" {
117 const a = inlineFn;
118 a();
119}
120
121inline fn inlineFn() void {}
122
123test "pass by non-copying value" {
124 assertOrPanic(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
125}
126
127const Point = struct {
128 x: i32,
129 y: i32,
130};
131
132fn addPointCoords(pt: Point) i32 {
133 return pt.x + pt.y;
134}
135
136test "pass by non-copying value through var arg" {
137 assertOrPanic(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
138}
139
140fn addPointCoordsVar(pt: var) i32 {
141 comptime assertOrPanic(@typeOf(pt) == Point);
142 return pt.x + pt.y;
143}
144
145test "pass by non-copying value as method" {
146 var pt = Point2{ .x = 1, .y = 2 };
147 assertOrPanic(pt.addPointCoords() == 3);
148}
149
150const Point2 = struct {
151 x: i32,
152 y: i32,
153
154 fn addPointCoords(self: Point2) i32 {
155 return self.x + self.y;
156 }
157};
158
159test "pass by non-copying value as method, which is generic" {
160 var pt = Point3{ .x = 1, .y = 2 };
161 assertOrPanic(pt.addPointCoords(i32) == 3);
162}
163
164const Point3 = struct {
165 x: i32,
166 y: i32,
167
168 fn addPointCoords(self: Point3, comptime T: type) i32 {
169 return self.x + self.y;
170 }
171};
172
173test "pass by non-copying value as method, at comptime" {
174 comptime {
175 var pt = Point2{ .x = 1, .y = 2 };
176 assertOrPanic(pt.addPointCoords() == 3);
177 }
178}
179
180fn outer(y: u32) fn (u32) u32 {
181 const Y = @typeOf(y);
182 const st = struct {
183 fn get(z: u32) u32 {
184 return z + @sizeOf(Y);
185 }
186 };
187 return st.get;
188}
189
190test "return inner function which references comptime variable of outer function" {
191 var func = outer(10);
192 assertOrPanic(func(3) == 7);
193}
194
195test "extern struct with stdcallcc fn pointer" {
196 const S = extern struct {
197 ptr: stdcallcc fn () i32,
198
199 stdcallcc fn foo() i32 {
200 return 1234;
201 }
202 };
203
204 var s: S = undefined;
205 s.ptr = S.foo;
206 assertOrPanic(s.ptr() == 1234);
207}
208
test/stage1/behavior/fn_in_struct_in_comptime.zig created+17
......@@ -0,0 +1,17 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3fn get_foo() fn (*u8) usize {
4 comptime {
5 return struct {
6 fn func(ptr: *u8) usize {
7 var u = @ptrToInt(ptr);
8 return u;
9 }
10 }.func;
11 }
12}
13
14test "define a function in an anonymous struct in comptime" {
15 const foo = get_foo();
16 assertOrPanic(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/stage1/behavior/for.zig created+106
......@@ -0,0 +1,106 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const mem = std.mem;
4
5test "continue in for loop" {
6 const array = []i32{
7 1,
8 2,
9 3,
10 4,
11 5,
12 };
13 var sum: i32 = 0;
14 for (array) |x| {
15 sum += x;
16 if (x < 3) {
17 continue;
18 }
19 break;
20 }
21 if (sum != 6) unreachable;
22}
23
24test "for loop with pointer elem var" {
25 const source = "abcdefg";
26 var target: [source.len]u8 = undefined;
27 mem.copy(u8, target[0..], source);
28 mangleString(target[0..]);
29 assertOrPanic(mem.eql(u8, target, "bcdefgh"));
30}
31fn mangleString(s: []u8) void {
32 for (s) |*c| {
33 c.* += 1;
34 }
35}
36
37test "basic for loop" {
38 const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
39
40 var buffer: [expected_result.len]u8 = undefined;
41 var buf_index: usize = 0;
42
43 const array = []u8{ 9, 8, 7, 6 };
44 for (array) |item| {
45 buffer[buf_index] = item;
46 buf_index += 1;
47 }
48 for (array) |item, index| {
49 buffer[buf_index] = @intCast(u8, index);
50 buf_index += 1;
51 }
52 const array_ptr = &array;
53 for (array_ptr) |item| {
54 buffer[buf_index] = item;
55 buf_index += 1;
56 }
57 for (array_ptr) |item, index| {
58 buffer[buf_index] = @intCast(u8, index);
59 buf_index += 1;
60 }
61 const unknown_size: []const u8 = array;
62 for (unknown_size) |item| {
63 buffer[buf_index] = item;
64 buf_index += 1;
65 }
66 for (unknown_size) |item, index| {
67 buffer[buf_index] = @intCast(u8, index);
68 buf_index += 1;
69 }
70
71 assertOrPanic(mem.eql(u8, buffer[0..buf_index], expected_result));
72}
73
74test "break from outer for loop" {
75 testBreakOuter();
76 comptime testBreakOuter();
77}
78
79fn testBreakOuter() void {
80 var array = "aoeu";
81 var count: usize = 0;
82 outer: for (array) |_| {
83 for (array) |_| {
84 count += 1;
85 break :outer;
86 }
87 }
88 assertOrPanic(count == 1);
89}
90
91test "continue outer for loop" {
92 testContinueOuter();
93 comptime testContinueOuter();
94}
95
96fn testContinueOuter() void {
97 var array = "aoeu";
98 var counter: usize = 0;
99 outer: for (array) |_| {
100 for (array) |_| {
101 counter += 1;
102 continue :outer;
103 }
104 }
105 assertOrPanic(counter == array.len);
106}
test/stage1/behavior/generics.zig created+151
......@@ -0,0 +1,151 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "simple generic fn" {
4 assertOrPanic(max(i32, 3, -1) == 3);
5 assertOrPanic(max(f32, 0.123, 0.456) == 0.456);
6 assertOrPanic(add(2, 3) == 5);
7}
8
9fn max(comptime T: type, a: T, b: T) T {
10 return if (a > b) a else b;
11}
12
13fn add(comptime a: i32, b: i32) i32 {
14 return (comptime a) + b;
15}
16
17const the_max = max(u32, 1234, 5678);
18test "compile time generic eval" {
19 assertOrPanic(the_max == 5678);
20}
21
22fn gimmeTheBigOne(a: u32, b: u32) u32 {
23 return max(u32, a, b);
24}
25
26fn shouldCallSameInstance(a: u32, b: u32) u32 {
27 return max(u32, a, b);
28}
29
30fn sameButWithFloats(a: f64, b: f64) f64 {
31 return max(f64, a, b);
32}
33
34test "fn with comptime args" {
35 assertOrPanic(gimmeTheBigOne(1234, 5678) == 5678);
36 assertOrPanic(shouldCallSameInstance(34, 12) == 34);
37 assertOrPanic(sameButWithFloats(0.43, 0.49) == 0.49);
38}
39
40test "var params" {
41 assertOrPanic(max_i32(12, 34) == 34);
42 assertOrPanic(max_f64(1.2, 3.4) == 3.4);
43}
44
45comptime {
46 assertOrPanic(max_i32(12, 34) == 34);
47 assertOrPanic(max_f64(1.2, 3.4) == 3.4);
48}
49
50fn max_var(a: var, b: var) @typeOf(a + b) {
51 return if (a > b) a else b;
52}
53
54fn max_i32(a: i32, b: i32) i32 {
55 return max_var(a, b);
56}
57
58fn max_f64(a: f64, b: f64) f64 {
59 return max_var(a, b);
60}
61
62pub fn List(comptime T: type) type {
63 return SmallList(T, 8);
64}
65
66pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
67 return struct {
68 items: []T,
69 length: usize,
70 prealloc_items: [STATIC_SIZE]T,
71 };
72}
73
74test "function with return type type" {
75 var list: List(i32) = undefined;
76 var list2: List(i32) = undefined;
77 list.length = 10;
78 list2.length = 10;
79 assertOrPanic(list.prealloc_items.len == 8);
80 assertOrPanic(list2.prealloc_items.len == 8);
81}
82
83test "generic struct" {
84 var a1 = GenNode(i32){
85 .value = 13,
86 .next = null,
87 };
88 var b1 = GenNode(bool){
89 .value = true,
90 .next = null,
91 };
92 assertOrPanic(a1.value == 13);
93 assertOrPanic(a1.value == a1.getVal());
94 assertOrPanic(b1.getVal());
95}
96fn GenNode(comptime T: type) type {
97 return struct {
98 value: T,
99 next: ?*GenNode(T),
100 fn getVal(n: *const GenNode(T)) T {
101 return n.value;
102 }
103 };
104}
105
106test "const decls in struct" {
107 assertOrPanic(GenericDataThing(3).count_plus_one == 4);
108}
109fn GenericDataThing(comptime count: isize) type {
110 return struct {
111 const count_plus_one = count + 1;
112 };
113}
114
115test "use generic param in generic param" {
116 assertOrPanic(aGenericFn(i32, 3, 4) == 7);
117}
118fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
119 return a + b;
120}
121
122test "generic fn with implicit cast" {
123 assertOrPanic(getFirstByte(u8, []u8{13}) == 13);
124 assertOrPanic(getFirstByte(u16, []u16{
125 0,
126 13,
127 }) == 0);
128}
129fn getByte(ptr: ?*const u8) u8 {
130 return ptr.?.*;
131}
132fn getFirstByte(comptime T: type, mem: []const T) u8 {
133 return getByte(@ptrCast(*const u8, &mem[0]));
134}
135
136const foos = []fn (var) bool{
137 foo1,
138 foo2,
139};
140
141fn foo1(arg: var) bool {
142 return arg;
143}
144fn foo2(arg: var) bool {
145 return !arg;
146}
147
148test "array of generic fns" {
149 assertOrPanic(foos[0](true));
150 assertOrPanic(!foos[1](true));
151}
test/stage1/behavior/if.zig created+37
......@@ -0,0 +1,37 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "if statements" {
4 shouldBeEqual(1, 1);
5 firstEqlThird(2, 1, 2);
6}
7fn shouldBeEqual(a: i32, b: i32) void {
8 if (a != b) {
9 unreachable;
10 } else {
11 return;
12 }
13}
14fn firstEqlThird(a: i32, b: i32, c: i32) void {
15 if (a == b) {
16 unreachable;
17 } else if (b == c) {
18 unreachable;
19 } else if (a == c) {
20 return;
21 } else {
22 unreachable;
23 }
24}
25
26test "else if expression" {
27 assertOrPanic(elseIfExpressionF(1) == 1);
28}
29fn elseIfExpressionF(c: u8) u8 {
30 if (c == 0) {
31 return 0;
32 } else if (c == 1) {
33 return 1;
34 } else {
35 return u8(2);
36 }
37}
test/stage1/behavior/import.zig created+10
......@@ -0,0 +1,10 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const a_namespace = @import("import/a_namespace.zig");
3
4test "call fn via namespace lookup" {
5 assertOrPanic(a_namespace.foo() == 1234);
6}
7
8test "importing the same thing gives the same import" {
9 assertOrPanic(@import("std") == @import("std"));
10}
test/stage1/behavior/import/a_namespace.zig created+3
......@@ -0,0 +1,3 @@
1pub fn foo() i32 {
2 return 1234;
3}
test/stage1/behavior/incomplete_struct_param_tld.zig created+30
......@@ -0,0 +1,30 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const A = struct {
4 b: B,
5};
6
7const B = struct {
8 c: C,
9};
10
11const C = struct {
12 x: i32,
13
14 fn d(c: *const C) i32 {
15 return c.x;
16 }
17};
18
19fn foo(a: A) i32 {
20 return a.b.c.d();
21}
22
23test "incomplete struct param top level declaration" {
24 const a = A{
25 .b = B{
26 .c = C{ .x = 13 },
27 },
28 };
29 assertOrPanic(foo(a) == 13);
30}
test/stage1/behavior/inttoptr.zig created+26
......@@ -0,0 +1,26 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "casting random address to function pointer" {
6 randomAddressToFunction();
7 comptime randomAddressToFunction();
8}
9
10fn randomAddressToFunction() void {
11 var addr: usize = 0xdeadbeef;
12 var ptr = @intToPtr(fn () void, addr);
13}
14
15test "mutate through ptr initialized with constant intToPtr value" {
16 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
17}
18
19fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
20 const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
21 if (x) {
22 hardCodedP.* = hardCodedP.* | 10;
23 } else {
24 return;
25 }
26}
test/stage1/behavior/ir_block_deps.zig created+21
......@@ -0,0 +1,21 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3fn foo(id: u64) !i32 {
4 return switch (id) {
5 1 => getErrInt(),
6 2 => {
7 const size = try getErrInt();
8 return try getErrInt();
9 },
10 else => error.ItBroke,
11 };
12}
13
14fn getErrInt() anyerror!i32 {
15 return 0;
16}
17
18test "ir block deps" {
19 assertOrPanic((foo(1) catch unreachable) == 0);
20 assertOrPanic((foo(2) catch unreachable) == 0);
21}
test/stage1/behavior/math.zig created+500
......@@ -0,0 +1,500 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const maxInt = std.math.maxInt;
4const minInt = std.math.minInt;
5
6test "division" {
7 testDivision();
8 comptime testDivision();
9}
10fn testDivision() void {
11 assertOrPanic(div(u32, 13, 3) == 4);
12 assertOrPanic(div(f16, 1.0, 2.0) == 0.5);
13 assertOrPanic(div(f32, 1.0, 2.0) == 0.5);
14
15 assertOrPanic(divExact(u32, 55, 11) == 5);
16 assertOrPanic(divExact(i32, -55, 11) == -5);
17 assertOrPanic(divExact(f16, 55.0, 11.0) == 5.0);
18 assertOrPanic(divExact(f16, -55.0, 11.0) == -5.0);
19 assertOrPanic(divExact(f32, 55.0, 11.0) == 5.0);
20 assertOrPanic(divExact(f32, -55.0, 11.0) == -5.0);
21
22 assertOrPanic(divFloor(i32, 5, 3) == 1);
23 assertOrPanic(divFloor(i32, -5, 3) == -2);
24 assertOrPanic(divFloor(f16, 5.0, 3.0) == 1.0);
25 assertOrPanic(divFloor(f16, -5.0, 3.0) == -2.0);
26 assertOrPanic(divFloor(f32, 5.0, 3.0) == 1.0);
27 assertOrPanic(divFloor(f32, -5.0, 3.0) == -2.0);
28 assertOrPanic(divFloor(i32, -0x80000000, -2) == 0x40000000);
29 assertOrPanic(divFloor(i32, 0, -0x80000000) == 0);
30 assertOrPanic(divFloor(i32, -0x40000001, 0x40000000) == -2);
31 assertOrPanic(divFloor(i32, -0x80000000, 1) == -0x80000000);
32
33 assertOrPanic(divTrunc(i32, 5, 3) == 1);
34 assertOrPanic(divTrunc(i32, -5, 3) == -1);
35 assertOrPanic(divTrunc(f16, 5.0, 3.0) == 1.0);
36 assertOrPanic(divTrunc(f16, -5.0, 3.0) == -1.0);
37 assertOrPanic(divTrunc(f32, 5.0, 3.0) == 1.0);
38 assertOrPanic(divTrunc(f32, -5.0, 3.0) == -1.0);
39 assertOrPanic(divTrunc(f64, 5.0, 3.0) == 1.0);
40 assertOrPanic(divTrunc(f64, -5.0, 3.0) == -1.0);
41
42 comptime {
43 assertOrPanic(
44 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
45 );
46 assertOrPanic(
47 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
48 );
49 assertOrPanic(
50 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
51 );
52 assertOrPanic(
53 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
54 );
55 assertOrPanic(
56 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
57 );
58 assertOrPanic(
59 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
60 );
61 assertOrPanic(
62 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
63 );
64 }
65}
66fn div(comptime T: type, a: T, b: T) T {
67 return a / b;
68}
69fn divExact(comptime T: type, a: T, b: T) T {
70 return @divExact(a, b);
71}
72fn divFloor(comptime T: type, a: T, b: T) T {
73 return @divFloor(a, b);
74}
75fn divTrunc(comptime T: type, a: T, b: T) T {
76 return @divTrunc(a, b);
77}
78
79test "@addWithOverflow" {
80 var result: u8 = undefined;
81 assertOrPanic(@addWithOverflow(u8, 250, 100, &result));
82 assertOrPanic(!@addWithOverflow(u8, 100, 150, &result));
83 assertOrPanic(result == 250);
84}
85
86// TODO test mulWithOverflow
87// TODO test subWithOverflow
88
89test "@shlWithOverflow" {
90 var result: u16 = undefined;
91 assertOrPanic(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
92 assertOrPanic(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
93 assertOrPanic(result == 0b1011111111111100);
94}
95
96test "@clz" {
97 testClz();
98 comptime testClz();
99}
100
101fn testClz() void {
102 assertOrPanic(clz(u8(0b00001010)) == 4);
103 assertOrPanic(clz(u8(0b10001010)) == 0);
104 assertOrPanic(clz(u8(0b00000000)) == 8);
105 assertOrPanic(clz(u128(0xffffffffffffffff)) == 64);
106 assertOrPanic(clz(u128(0x10000000000000000)) == 63);
107}
108
109fn clz(x: var) usize {
110 return @clz(x);
111}
112
113test "@ctz" {
114 testCtz();
115 comptime testCtz();
116}
117
118fn testCtz() void {
119 assertOrPanic(ctz(u8(0b10100000)) == 5);
120 assertOrPanic(ctz(u8(0b10001010)) == 1);
121 assertOrPanic(ctz(u8(0b00000000)) == 8);
122}
123
124fn ctz(x: var) usize {
125 return @ctz(x);
126}
127
128test "assignment operators" {
129 var i: u32 = 0;
130 i += 5;
131 assertOrPanic(i == 5);
132 i -= 2;
133 assertOrPanic(i == 3);
134 i *= 20;
135 assertOrPanic(i == 60);
136 i /= 3;
137 assertOrPanic(i == 20);
138 i %= 11;
139 assertOrPanic(i == 9);
140 i <<= 1;
141 assertOrPanic(i == 18);
142 i >>= 2;
143 assertOrPanic(i == 4);
144 i = 6;
145 i &= 5;
146 assertOrPanic(i == 4);
147 i ^= 6;
148 assertOrPanic(i == 2);
149 i = 6;
150 i |= 3;
151 assertOrPanic(i == 7);
152}
153
154test "three expr in a row" {
155 testThreeExprInARow(false, true);
156 comptime testThreeExprInARow(false, true);
157}
158fn testThreeExprInARow(f: bool, t: bool) void {
159 assertFalse(f or f or f);
160 assertFalse(t and t and f);
161 assertFalse(1 | 2 | 4 != 7);
162 assertFalse(3 ^ 6 ^ 8 != 13);
163 assertFalse(7 & 14 & 28 != 4);
164 assertFalse(9 << 1 << 2 != 9 << 3);
165 assertFalse(90 >> 1 >> 2 != 90 >> 3);
166 assertFalse(100 - 1 + 1000 != 1099);
167 assertFalse(5 * 4 / 2 % 3 != 1);
168 assertFalse(i32(i32(5)) != 5);
169 assertFalse(!!false);
170 assertFalse(i32(7) != --(i32(7)));
171}
172fn assertFalse(b: bool) void {
173 assertOrPanic(!b);
174}
175
176test "const number literal" {
177 const one = 1;
178 const eleven = ten + one;
179
180 assertOrPanic(eleven == 11);
181}
182const ten = 10;
183
184test "unsigned wrapping" {
185 testUnsignedWrappingEval(maxInt(u32));
186 comptime testUnsignedWrappingEval(maxInt(u32));
187}
188fn testUnsignedWrappingEval(x: u32) void {
189 const zero = x +% 1;
190 assertOrPanic(zero == 0);
191 const orig = zero -% 1;
192 assertOrPanic(orig == maxInt(u32));
193}
194
195test "signed wrapping" {
196 testSignedWrappingEval(maxInt(i32));
197 comptime testSignedWrappingEval(maxInt(i32));
198}
199fn testSignedWrappingEval(x: i32) void {
200 const min_val = x +% 1;
201 assertOrPanic(min_val == minInt(i32));
202 const max_val = min_val -% 1;
203 assertOrPanic(max_val == maxInt(i32));
204}
205
206test "negation wrapping" {
207 testNegationWrappingEval(minInt(i16));
208 comptime testNegationWrappingEval(minInt(i16));
209}
210fn testNegationWrappingEval(x: i16) void {
211 assertOrPanic(x == -32768);
212 const neg = -%x;
213 assertOrPanic(neg == -32768);
214}
215
216test "unsigned 64-bit division" {
217 test_u64_div();
218 comptime test_u64_div();
219}
220fn test_u64_div() void {
221 const result = divWithResult(1152921504606846976, 34359738365);
222 assertOrPanic(result.quotient == 33554432);
223 assertOrPanic(result.remainder == 100663296);
224}
225fn divWithResult(a: u64, b: u64) DivResult {
226 return DivResult{
227 .quotient = a / b,
228 .remainder = a % b,
229 };
230}
231const DivResult = struct {
232 quotient: u64,
233 remainder: u64,
234};
235
236test "binary not" {
237 assertOrPanic(comptime x: {
238 break :x ~u16(0b1010101010101010) == 0b0101010101010101;
239 });
240 assertOrPanic(comptime x: {
241 break :x ~u64(2147483647) == 18446744071562067968;
242 });
243 testBinaryNot(0b1010101010101010);
244}
245
246fn testBinaryNot(x: u16) void {
247 assertOrPanic(~x == 0b0101010101010101);
248}
249
250test "small int addition" {
251 var x: @IntType(false, 2) = 0;
252 assertOrPanic(x == 0);
253
254 x += 1;
255 assertOrPanic(x == 1);
256
257 x += 1;
258 assertOrPanic(x == 2);
259
260 x += 1;
261 assertOrPanic(x == 3);
262
263 var result: @typeOf(x) = 3;
264 assertOrPanic(@addWithOverflow(@typeOf(x), x, 1, &result));
265
266 assertOrPanic(result == 0);
267}
268
269test "float equality" {
270 const x: f64 = 0.012;
271 const y: f64 = x + 1.0;
272
273 testFloatEqualityImpl(x, y);
274 comptime testFloatEqualityImpl(x, y);
275}
276
277fn testFloatEqualityImpl(x: f64, y: f64) void {
278 const y2 = x + 1.0;
279 assertOrPanic(y == y2);
280}
281
282test "allow signed integer division/remainder when values are comptime known and positive or exact" {
283 assertOrPanic(5 / 3 == 1);
284 assertOrPanic(-5 / -3 == 1);
285 assertOrPanic(-6 / 3 == -2);
286
287 assertOrPanic(5 % 3 == 2);
288 assertOrPanic(-6 % 3 == 0);
289}
290
291test "hex float literal parsing" {
292 comptime assertOrPanic(0x1.0 == 1.0);
293}
294
295test "quad hex float literal parsing in range" {
296 const a = 0x1.af23456789bbaaab347645365cdep+5;
297 const b = 0x1.dedafcff354b6ae9758763545432p-9;
298 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
299 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
300}
301
302test "quad hex float literal parsing accurate" {
303 const a: f128 = 0x1.1111222233334444555566667777p+0;
304
305 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
306 const expected: u128 = 0x3fff1111222233334444555566667777;
307 assertOrPanic(@bitCast(u128, a) == expected);
308}
309
310test "hex float literal within range" {
311 const a = 0x1.0p16383;
312 const b = 0x0.1p16387;
313 const c = 0x1.0p-16382;
314}
315
316test "truncating shift left" {
317 testShlTrunc(maxInt(u16));
318 comptime testShlTrunc(maxInt(u16));
319}
320fn testShlTrunc(x: u16) void {
321 const shifted = x << 1;
322 assertOrPanic(shifted == 65534);
323}
324
325test "truncating shift right" {
326 testShrTrunc(maxInt(u16));
327 comptime testShrTrunc(maxInt(u16));
328}
329fn testShrTrunc(x: u16) void {
330 const shifted = x >> 1;
331 assertOrPanic(shifted == 32767);
332}
333
334test "exact shift left" {
335 testShlExact(0b00110101);
336 comptime testShlExact(0b00110101);
337}
338fn testShlExact(x: u8) void {
339 const shifted = @shlExact(x, 2);
340 assertOrPanic(shifted == 0b11010100);
341}
342
343test "exact shift right" {
344 testShrExact(0b10110100);
345 comptime testShrExact(0b10110100);
346}
347fn testShrExact(x: u8) void {
348 const shifted = @shrExact(x, 2);
349 assertOrPanic(shifted == 0b00101101);
350}
351
352test "comptime_int addition" {
353 comptime {
354 assertOrPanic(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
355 assertOrPanic(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
356 }
357}
358
359test "comptime_int multiplication" {
360 comptime {
361 assertOrPanic(
362 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
363 );
364 assertOrPanic(
365 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
366 );
367 }
368}
369
370test "comptime_int shifting" {
371 comptime {
372 assertOrPanic((u128(1) << 127) == 0x80000000000000000000000000000000);
373 }
374}
375
376test "comptime_int multi-limb shift and mask" {
377 comptime {
378 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
379
380 assertOrPanic(u32(a & 0xffffffff) == 0xaaaaaaab);
381 a >>= 32;
382 assertOrPanic(u32(a & 0xffffffff) == 0xeeeeeeef);
383 a >>= 32;
384 assertOrPanic(u32(a & 0xffffffff) == 0xa0000001);
385 a >>= 32;
386 assertOrPanic(u32(a & 0xffffffff) == 0xefffffff);
387 a >>= 32;
388
389 assertOrPanic(a == 0);
390 }
391}
392
393test "comptime_int multi-limb partial shift right" {
394 comptime {
395 var a = 0x1ffffffffeeeeeeee;
396 a >>= 16;
397 assertOrPanic(a == 0x1ffffffffeeee);
398 }
399}
400
401test "xor" {
402 test_xor();
403 comptime test_xor();
404}
405
406fn test_xor() void {
407 assertOrPanic(0xFF ^ 0x00 == 0xFF);
408 assertOrPanic(0xF0 ^ 0x0F == 0xFF);
409 assertOrPanic(0xFF ^ 0xF0 == 0x0F);
410 assertOrPanic(0xFF ^ 0x0F == 0xF0);
411 assertOrPanic(0xFF ^ 0xFF == 0x00);
412}
413
414test "comptime_int xor" {
415 comptime {
416 assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
417 assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
418 assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
419 assertOrPanic(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
420 assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
421 assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
422 assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
423 assertOrPanic(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
424 }
425}
426
427test "f128" {
428 test_f128();
429 comptime test_f128();
430}
431
432fn make_f128(x: f128) f128 {
433 return x;
434}
435
436fn test_f128() void {
437 assertOrPanic(@sizeOf(f128) == 16);
438 assertOrPanic(make_f128(1.0) == 1.0);
439 assertOrPanic(make_f128(1.0) != 1.1);
440 assertOrPanic(make_f128(1.0) > 0.9);
441 assertOrPanic(make_f128(1.0) >= 0.9);
442 assertOrPanic(make_f128(1.0) >= 1.0);
443 should_not_be_zero(1.0);
444}
445
446fn should_not_be_zero(x: f128) void {
447 assertOrPanic(x != 0.0);
448}
449
450test "comptime float rem int" {
451 comptime {
452 var x = f32(1) % 2;
453 assertOrPanic(x == 1.0);
454 }
455}
456
457test "remainder division" {
458 comptime remdiv(f16);
459 comptime remdiv(f32);
460 comptime remdiv(f64);
461 comptime remdiv(f128);
462 remdiv(f16);
463 remdiv(f64);
464 remdiv(f128);
465}
466
467fn remdiv(comptime T: type) void {
468 assertOrPanic(T(1) == T(1) % T(2));
469 assertOrPanic(T(1) == T(7) % T(3));
470}
471
472test "@sqrt" {
473 testSqrt(f64, 12.0);
474 comptime testSqrt(f64, 12.0);
475 testSqrt(f32, 13.0);
476 comptime testSqrt(f32, 13.0);
477 testSqrt(f16, 13.0);
478 comptime testSqrt(f16, 13.0);
479
480 const x = 14.0;
481 const y = x * x;
482 const z = @sqrt(@typeOf(y), y);
483 comptime assertOrPanic(z == x);
484}
485
486fn testSqrt(comptime T: type, x: T) void {
487 assertOrPanic(@sqrt(T, x * x) == x);
488}
489
490test "comptime_int param and return" {
491 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
492 assertOrPanic(a == 137114567242441932203689521744947848950);
493
494 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
495 assertOrPanic(b == 985095453608931032642182098849559179469148836107390954364380);
496}
497
498fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
499 return a + b;
500}
test/stage1/behavior/merge_error_sets.zig created+21
......@@ -0,0 +1,21 @@
1const A = error{
2 FileNotFound,
3 NotDir,
4};
5const B = error{OutOfMemory};
6
7const C = A || B;
8
9fn foo() C!void {
10 return error.NotDir;
11}
12
13test "merge error sets" {
14 if (foo()) {
15 @panic("unexpected");
16 } else |err| switch (err) {
17 error.OutOfMemory => @panic("unexpected"),
18 error.FileNotFound => @panic("unexpected"),
19 error.NotDir => {},
20 }
21}
test/stage1/behavior/misc.zig created+687
......@@ -0,0 +1,687 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const mem = std.mem;
4const cstr = std.cstr;
5const builtin = @import("builtin");
6const maxInt = std.math.maxInt;
7
8// normal comment
9
10/// this is a documentation comment
11/// doc comment line 2
12fn emptyFunctionWithComments() void {}
13
14test "empty function with comments" {
15 emptyFunctionWithComments();
16}
17
18comptime {
19 @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
20}
21
22extern fn disabledExternFn() void {}
23
24test "call disabled extern fn" {
25 disabledExternFn();
26}
27
28test "@IntType builtin" {
29 assertOrPanic(@IntType(true, 8) == i8);
30 assertOrPanic(@IntType(true, 16) == i16);
31 assertOrPanic(@IntType(true, 32) == i32);
32 assertOrPanic(@IntType(true, 64) == i64);
33
34 assertOrPanic(@IntType(false, 8) == u8);
35 assertOrPanic(@IntType(false, 16) == u16);
36 assertOrPanic(@IntType(false, 32) == u32);
37 assertOrPanic(@IntType(false, 64) == u64);
38
39 assertOrPanic(i8.bit_count == 8);
40 assertOrPanic(i16.bit_count == 16);
41 assertOrPanic(i32.bit_count == 32);
42 assertOrPanic(i64.bit_count == 64);
43
44 assertOrPanic(i8.is_signed);
45 assertOrPanic(i16.is_signed);
46 assertOrPanic(i32.is_signed);
47 assertOrPanic(i64.is_signed);
48 assertOrPanic(isize.is_signed);
49
50 assertOrPanic(!u8.is_signed);
51 assertOrPanic(!u16.is_signed);
52 assertOrPanic(!u32.is_signed);
53 assertOrPanic(!u64.is_signed);
54 assertOrPanic(!usize.is_signed);
55}
56
57test "floating point primitive bit counts" {
58 assertOrPanic(f16.bit_count == 16);
59 assertOrPanic(f32.bit_count == 32);
60 assertOrPanic(f64.bit_count == 64);
61}
62
63test "short circuit" {
64 testShortCircuit(false, true);
65 comptime testShortCircuit(false, true);
66}
67
68fn testShortCircuit(f: bool, t: bool) void {
69 var hit_1 = f;
70 var hit_2 = f;
71 var hit_3 = f;
72 var hit_4 = f;
73
74 if (t or x: {
75 assertOrPanic(f);
76 break :x f;
77 }) {
78 hit_1 = t;
79 }
80 if (f or x: {
81 hit_2 = t;
82 break :x f;
83 }) {
84 assertOrPanic(f);
85 }
86
87 if (t and x: {
88 hit_3 = t;
89 break :x f;
90 }) {
91 assertOrPanic(f);
92 }
93 if (f and x: {
94 assertOrPanic(f);
95 break :x f;
96 }) {
97 assertOrPanic(f);
98 } else {
99 hit_4 = t;
100 }
101 assertOrPanic(hit_1);
102 assertOrPanic(hit_2);
103 assertOrPanic(hit_3);
104 assertOrPanic(hit_4);
105}
106
107test "truncate" {
108 assertOrPanic(testTruncate(0x10fd) == 0xfd);
109}
110fn testTruncate(x: u32) u8 {
111 return @truncate(u8, x);
112}
113
114fn first4KeysOfHomeRow() []const u8 {
115 return "aoeu";
116}
117
118test "return string from function" {
119 assertOrPanic(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
120}
121
122const g1: i32 = 1233 + 1;
123var g2: i32 = 0;
124
125test "global variables" {
126 assertOrPanic(g2 == 0);
127 g2 = g1;
128 assertOrPanic(g2 == 1234);
129}
130
131test "memcpy and memset intrinsics" {
132 var foo: [20]u8 = undefined;
133 var bar: [20]u8 = undefined;
134
135 @memset(foo[0..].ptr, 'A', foo.len);
136 @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
137
138 if (bar[11] != 'A') unreachable;
139}
140
141test "builtin static eval" {
142 const x: i32 = comptime x: {
143 break :x 1 + 2 + 3;
144 };
145 assertOrPanic(x == comptime 6);
146}
147
148test "slicing" {
149 var array: [20]i32 = undefined;
150
151 array[5] = 1234;
152
153 var slice = array[5..10];
154
155 if (slice.len != 5) unreachable;
156
157 const ptr = &slice[0];
158 if (ptr.* != 1234) unreachable;
159
160 var slice_rest = array[10..];
161 if (slice_rest.len != 10) unreachable;
162}
163
164test "constant equal function pointers" {
165 const alias = emptyFn;
166 assertOrPanic(comptime x: {
167 break :x emptyFn == alias;
168 });
169}
170
171fn emptyFn() void {}
172
173test "hex escape" {
174 assertOrPanic(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
175}
176
177test "string concatenation" {
178 assertOrPanic(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
179}
180
181test "array mult operator" {
182 assertOrPanic(mem.eql(u8, "ab" ** 5, "ababababab"));
183}
184
185test "string escapes" {
186 assertOrPanic(mem.eql(u8, "\"", "\x22"));
187 assertOrPanic(mem.eql(u8, "\'", "\x27"));
188 assertOrPanic(mem.eql(u8, "\n", "\x0a"));
189 assertOrPanic(mem.eql(u8, "\r", "\x0d"));
190 assertOrPanic(mem.eql(u8, "\t", "\x09"));
191 assertOrPanic(mem.eql(u8, "\\", "\x5c"));
192 assertOrPanic(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
193}
194
195test "multiline string" {
196 const s1 =
197 \\one
198 \\two)
199 \\three
200 ;
201 const s2 = "one\ntwo)\nthree";
202 assertOrPanic(mem.eql(u8, s1, s2));
203}
204
205test "multiline C string" {
206 const s1 =
207 c\\one
208 c\\two)
209 c\\three
210 ;
211 const s2 = c"one\ntwo)\nthree";
212 assertOrPanic(cstr.cmp(s1, s2) == 0);
213}
214
215test "type equality" {
216 assertOrPanic(*const u8 != *u8);
217}
218
219const global_a: i32 = 1234;
220const global_b: *const i32 = &global_a;
221const global_c: *const f32 = @ptrCast(*const f32, global_b);
222test "compile time global reinterpret" {
223 const d = @ptrCast(*const i32, global_c);
224 assertOrPanic(d.* == 1234);
225}
226
227test "explicit cast maybe pointers" {
228 const a: ?*i32 = undefined;
229 const b: ?*f32 = @ptrCast(?*f32, a);
230}
231
232test "generic malloc free" {
233 const a = memAlloc(u8, 10) catch unreachable;
234 memFree(u8, a);
235}
236var some_mem: [100]u8 = undefined;
237fn memAlloc(comptime T: type, n: usize) anyerror![]T {
238 return @ptrCast([*]T, &some_mem[0])[0..n];
239}
240fn memFree(comptime T: type, memory: []T) void {}
241
242test "cast undefined" {
243 const array: [100]u8 = undefined;
244 const slice = ([]const u8)(array);
245 testCastUndefined(slice);
246}
247fn testCastUndefined(x: []const u8) void {}
248
249test "cast small unsigned to larger signed" {
250 assertOrPanic(castSmallUnsignedToLargerSigned1(200) == i16(200));
251 assertOrPanic(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
252}
253fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
254 return x;
255}
256fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
257 return x;
258}
259
260test "implicit cast after unreachable" {
261 assertOrPanic(outer() == 1234);
262}
263fn inner() i32 {
264 return 1234;
265}
266fn outer() i64 {
267 return inner();
268}
269
270test "pointer dereferencing" {
271 var x = i32(3);
272 const y = &x;
273
274 y.* += 1;
275
276 assertOrPanic(x == 4);
277 assertOrPanic(y.* == 4);
278}
279
280test "call result of if else expression" {
281 assertOrPanic(mem.eql(u8, f2(true), "a"));
282 assertOrPanic(mem.eql(u8, f2(false), "b"));
283}
284fn f2(x: bool) []const u8 {
285 return (if (x) fA else fB)();
286}
287fn fA() []const u8 {
288 return "a";
289}
290fn fB() []const u8 {
291 return "b";
292}
293
294test "const expression eval handling of variables" {
295 var x = true;
296 while (x) {
297 x = false;
298 }
299}
300
301test "constant enum initialization with differing sizes" {
302 test3_1(test3_foo);
303 test3_2(test3_bar);
304}
305const Test3Foo = union(enum) {
306 One: void,
307 Two: f32,
308 Three: Test3Point,
309};
310const Test3Point = struct {
311 x: i32,
312 y: i32,
313};
314const test3_foo = Test3Foo{
315 .Three = Test3Point{
316 .x = 3,
317 .y = 4,
318 },
319};
320const test3_bar = Test3Foo{ .Two = 13 };
321fn test3_1(f: Test3Foo) void {
322 switch (f) {
323 Test3Foo.Three => |pt| {
324 assertOrPanic(pt.x == 3);
325 assertOrPanic(pt.y == 4);
326 },
327 else => unreachable,
328 }
329}
330fn test3_2(f: Test3Foo) void {
331 switch (f) {
332 Test3Foo.Two => |x| {
333 assertOrPanic(x == 13);
334 },
335 else => unreachable,
336 }
337}
338
339test "character literals" {
340 assertOrPanic('\'' == single_quote);
341}
342const single_quote = '\'';
343
344test "take address of parameter" {
345 testTakeAddressOfParameter(12.34);
346}
347fn testTakeAddressOfParameter(f: f32) void {
348 const f_ptr = &f;
349 assertOrPanic(f_ptr.* == 12.34);
350}
351
352test "pointer comparison" {
353 const a = ([]const u8)("a");
354 const b = &a;
355 assertOrPanic(ptrEql(b, b));
356}
357fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
358 return a == b;
359}
360
361test "C string concatenation" {
362 const a = c"OK" ++ c" IT " ++ c"WORKED";
363 const b = c"OK IT WORKED";
364
365 const len = cstr.len(b);
366 const len_with_null = len + 1;
367 {
368 var i: u32 = 0;
369 while (i < len_with_null) : (i += 1) {
370 assertOrPanic(a[i] == b[i]);
371 }
372 }
373 assertOrPanic(a[len] == 0);
374 assertOrPanic(b[len] == 0);
375}
376
377test "cast slice to u8 slice" {
378 assertOrPanic(@sizeOf(i32) == 4);
379 var big_thing_array = []i32{ 1, 2, 3, 4 };
380 const big_thing_slice: []i32 = big_thing_array[0..];
381 const bytes = @sliceToBytes(big_thing_slice);
382 assertOrPanic(bytes.len == 4 * 4);
383 bytes[4] = 0;
384 bytes[5] = 0;
385 bytes[6] = 0;
386 bytes[7] = 0;
387 assertOrPanic(big_thing_slice[1] == 0);
388 const big_thing_again = @bytesToSlice(i32, bytes);
389 assertOrPanic(big_thing_again[2] == 3);
390 big_thing_again[2] = -1;
391 assertOrPanic(bytes[8] == maxInt(u8));
392 assertOrPanic(bytes[9] == maxInt(u8));
393 assertOrPanic(bytes[10] == maxInt(u8));
394 assertOrPanic(bytes[11] == maxInt(u8));
395}
396
397test "pointer to void return type" {
398 testPointerToVoidReturnType() catch unreachable;
399}
400fn testPointerToVoidReturnType() anyerror!void {
401 const a = testPointerToVoidReturnType2();
402 return a.*;
403}
404const test_pointer_to_void_return_type_x = void{};
405fn testPointerToVoidReturnType2() *const void {
406 return &test_pointer_to_void_return_type_x;
407}
408
409test "non const ptr to aliased type" {
410 const int = i32;
411 assertOrPanic(?*int == ?*i32);
412}
413
414test "array 2D const double ptr" {
415 const rect_2d_vertexes = [][1]f32{
416 []f32{1.0},
417 []f32{2.0},
418 };
419 testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
420}
421
422fn testArray2DConstDoublePtr(ptr: *const f32) void {
423 const ptr2 = @ptrCast([*]const f32, ptr);
424 assertOrPanic(ptr2[0] == 1.0);
425 assertOrPanic(ptr2[1] == 2.0);
426}
427
428const Tid = builtin.TypeId;
429const AStruct = struct {
430 x: i32,
431};
432const AnEnum = enum {
433 One,
434 Two,
435};
436const AUnionEnum = union(enum) {
437 One: i32,
438 Two: void,
439};
440const AUnion = union {
441 One: void,
442 Two: void,
443};
444
445test "@typeId" {
446 comptime {
447 assertOrPanic(@typeId(type) == Tid.Type);
448 assertOrPanic(@typeId(void) == Tid.Void);
449 assertOrPanic(@typeId(bool) == Tid.Bool);
450 assertOrPanic(@typeId(noreturn) == Tid.NoReturn);
451 assertOrPanic(@typeId(i8) == Tid.Int);
452 assertOrPanic(@typeId(u8) == Tid.Int);
453 assertOrPanic(@typeId(i64) == Tid.Int);
454 assertOrPanic(@typeId(u64) == Tid.Int);
455 assertOrPanic(@typeId(f32) == Tid.Float);
456 assertOrPanic(@typeId(f64) == Tid.Float);
457 assertOrPanic(@typeId(*f32) == Tid.Pointer);
458 assertOrPanic(@typeId([2]u8) == Tid.Array);
459 assertOrPanic(@typeId(AStruct) == Tid.Struct);
460 assertOrPanic(@typeId(@typeOf(1)) == Tid.ComptimeInt);
461 assertOrPanic(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
462 assertOrPanic(@typeId(@typeOf(undefined)) == Tid.Undefined);
463 assertOrPanic(@typeId(@typeOf(null)) == Tid.Null);
464 assertOrPanic(@typeId(?i32) == Tid.Optional);
465 assertOrPanic(@typeId(anyerror!i32) == Tid.ErrorUnion);
466 assertOrPanic(@typeId(anyerror) == Tid.ErrorSet);
467 assertOrPanic(@typeId(AnEnum) == Tid.Enum);
468 assertOrPanic(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
469 assertOrPanic(@typeId(AUnionEnum) == Tid.Union);
470 assertOrPanic(@typeId(AUnion) == Tid.Union);
471 assertOrPanic(@typeId(fn () void) == Tid.Fn);
472 assertOrPanic(@typeId(@typeOf(builtin)) == Tid.Namespace);
473 // TODO bound fn
474 // TODO arg tuple
475 // TODO opaque
476 }
477}
478
479test "@typeName" {
480 const Struct = struct {};
481 const Union = union {
482 unused: u8,
483 };
484 const Enum = enum {
485 Unused,
486 };
487 comptime {
488 assertOrPanic(mem.eql(u8, @typeName(i64), "i64"));
489 assertOrPanic(mem.eql(u8, @typeName(*usize), "*usize"));
490 // https://github.com/ziglang/zig/issues/675
491 assertOrPanic(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
492 assertOrPanic(mem.eql(u8, @typeName(Struct), "Struct"));
493 assertOrPanic(mem.eql(u8, @typeName(Union), "Union"));
494 assertOrPanic(mem.eql(u8, @typeName(Enum), "Enum"));
495 }
496}
497
498fn TypeFromFn(comptime T: type) type {
499 return struct {};
500}
501
502test "double implicit cast in same expression" {
503 var x = i32(u16(nine()));
504 assertOrPanic(x == 9);
505}
506fn nine() u8 {
507 return 9;
508}
509
510test "global variable initialized to global variable array element" {
511 assertOrPanic(global_ptr == &gdt[0]);
512}
513const GDTEntry = struct {
514 field: i32,
515};
516var gdt = []GDTEntry{
517 GDTEntry{ .field = 1 },
518 GDTEntry{ .field = 2 },
519};
520var global_ptr = &gdt[0];
521
522// can't really run this test but we can make sure it has no compile error
523// and generates code
524const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
525export fn writeToVRam() void {
526 vram[0] = 'X';
527}
528
529const OpaqueA = @OpaqueType();
530const OpaqueB = @OpaqueType();
531test "@OpaqueType" {
532 assertOrPanic(*OpaqueA != *OpaqueB);
533 assertOrPanic(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
534 assertOrPanic(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
535}
536
537test "variable is allowed to be a pointer to an opaque type" {
538 var x: i32 = 1234;
539 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
540}
541fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
542 var a = ptr;
543 return a;
544}
545
546test "comptime if inside runtime while which unconditionally breaks" {
547 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
548 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
549}
550fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
551 while (cond) {
552 if (false) {}
553 break;
554 }
555}
556
557test "implicit comptime while" {
558 while (false) {
559 @compileError("bad");
560 }
561}
562
563fn fnThatClosesOverLocalConst() type {
564 const c = 1;
565 return struct {
566 fn g() i32 {
567 return c;
568 }
569 };
570}
571
572test "function closes over local const" {
573 const x = fnThatClosesOverLocalConst().g();
574 assertOrPanic(x == 1);
575}
576
577test "cold function" {
578 thisIsAColdFn();
579 comptime thisIsAColdFn();
580}
581
582fn thisIsAColdFn() void {
583 @setCold(true);
584}
585
586const PackedStruct = packed struct {
587 a: u8,
588 b: u8,
589};
590const PackedUnion = packed union {
591 a: u8,
592 b: u32,
593};
594const PackedEnum = packed enum {
595 A,
596 B,
597};
598
599test "packed struct, enum, union parameters in extern function" {
600 testPackedStuff(&(PackedStruct{
601 .a = 1,
602 .b = 2,
603 }), &(PackedUnion{ .a = 1 }), PackedEnum.A);
604}
605
606export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
607
608test "slicing zero length array" {
609 const s1 = ""[0..];
610 const s2 = ([]u32{})[0..];
611 assertOrPanic(s1.len == 0);
612 assertOrPanic(s2.len == 0);
613 assertOrPanic(mem.eql(u8, s1, ""));
614 assertOrPanic(mem.eql(u32, s2, []u32{}));
615}
616
617const addr1 = @ptrCast(*const u8, emptyFn);
618test "comptime cast fn to ptr" {
619 const addr2 = @ptrCast(*const u8, emptyFn);
620 comptime assertOrPanic(addr1 == addr2);
621}
622
623test "equality compare fn ptrs" {
624 var a = emptyFn;
625 assertOrPanic(a == a);
626}
627
628test "self reference through fn ptr field" {
629 const S = struct {
630 const A = struct {
631 f: fn (A) u8,
632 };
633
634 fn foo(a: A) u8 {
635 return 12;
636 }
637 };
638 var a: S.A = undefined;
639 a.f = S.foo;
640 assertOrPanic(a.f(a) == 12);
641}
642
643test "volatile load and store" {
644 var number: i32 = 1234;
645 const ptr = (*volatile i32)(&number);
646 ptr.* += 1;
647 assertOrPanic(ptr.* == 1235);
648}
649
650test "slice string literal has type []const u8" {
651 comptime {
652 assertOrPanic(@typeOf("aoeu"[0..]) == []const u8);
653 const array = []i32{ 1, 2, 3, 4 };
654 assertOrPanic(@typeOf(array[0..]) == []const i32);
655 }
656}
657
658test "pointer child field" {
659 assertOrPanic((*u32).Child == u32);
660}
661
662test "struct inside function" {
663 testStructInFn();
664 comptime testStructInFn();
665}
666
667fn testStructInFn() void {
668 const BlockKind = u32;
669
670 const Block = struct {
671 kind: BlockKind,
672 };
673
674 var block = Block{ .kind = 1234 };
675
676 block.kind += 1;
677
678 assertOrPanic(block.kind == 1235);
679}
680
681test "fn call returning scalar optional in equality expression" {
682 assertOrPanic(getNull() == null);
683}
684
685fn getNull() ?*i32 {
686 return null;
687}
test/stage1/behavior/namespace_depends_on_compile_var/a.zig created+1
......@@ -0,0 +1 @@
1pub const a_bool = true;
test/stage1/behavior/namespace_depends_on_compile_var/b.zig created+1
......@@ -0,0 +1 @@
1pub const a_bool = false;
test/stage1/behavior/namespace_depends_on_compile_var/index.zig created+14
......@@ -0,0 +1,14 @@
1const builtin = @import("builtin");
2const assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 assertOrPanic(some_namespace.a_bool);
7 } else {
8 assertOrPanic(!some_namespace.a_bool);
9 }
10}
11const some_namespace = switch (builtin.os) {
12 builtin.Os.linux => @import("a.zig"),
13 else => @import("b.zig"),
14};
test/stage1/behavior/new_stack_call.zig created+26
......@@ -0,0 +1,26 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4var new_stack_bytes: [1024]u8 = undefined;
5
6test "calling a function with a new stack" {
7 const arg = 1234;
8
9 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
10 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
11 _ = targetFunction(arg);
12
13 assertOrPanic(arg == 1234);
14 assertOrPanic(a < b);
15}
16
17fn targetFunction(x: i32) usize {
18 assertOrPanic(x == 1234);
19
20 var local_variable: i32 = 42;
21 const ptr = &local_variable;
22 ptr.* += 1;
23
24 assertOrPanic(local_variable == 43);
25 return @ptrToInt(ptr);
26}
test/stage1/behavior/null.zig created+162
......@@ -0,0 +1,162 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "optional type" {
4 const x: ?bool = true;
5
6 if (x) |y| {
7 if (y) {
8 // OK
9 } else {
10 unreachable;
11 }
12 } else {
13 unreachable;
14 }
15
16 const next_x: ?i32 = null;
17
18 const z = next_x orelse 1234;
19
20 assertOrPanic(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 assertOrPanic(num == 13);
27}
28
29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;
31
32 if (maybe_bool) |*b| {
33 b.* = false;
34 }
35
36 assertOrPanic(maybe_bool.? == false);
37}
38
39test "rhs maybe unwrap return" {
40 const x: ?bool = true;
41 const y = x orelse return;
42}
43
44test "maybe return" {
45 maybeReturnImpl();
46 comptime maybeReturnImpl();
47}
48
49fn maybeReturnImpl() void {
50 assertOrPanic(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 assertOrPanic(!foo(1234).?);
53}
54
55fn foo(x: ?i32) ?bool {
56 const value = x orelse return null;
57 return value > 1234;
58}
59
60test "if var maybe pointer" {
61 assertOrPanic(shouldBeAPlus1(Particle{
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
67}
68fn shouldBeAPlus1(p: Particle) u64 {
69 var maybe_particle: ?Particle = p;
70 if (maybe_particle) |*particle| {
71 particle.a += 1;
72 }
73 if (maybe_particle) |particle| {
74 return particle.a;
75 }
76 return 0;
77}
78const Particle = struct {
79 a: u64,
80 b: u64,
81 c: u64,
82 d: u64,
83};
84
85test "null literal outside function" {
86 const is_null = here_is_a_null_literal.context == null;
87 assertOrPanic(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 assertOrPanic(!is_non_null);
91}
92const SillyStruct = struct {
93 context: ?i32,
94};
95const here_is_a_null_literal = SillyStruct{ .context = null };
96
97test "test null runtime" {
98 testTestNullRuntime(null);
99}
100fn testTestNullRuntime(x: ?i32) void {
101 assertOrPanic(x == null);
102 assertOrPanic(!(x != null));
103}
104
105test "optional void" {
106 optionalVoidImpl();
107 comptime optionalVoidImpl();
108}
109
110fn optionalVoidImpl() void {
111 assertOrPanic(bar(null) == null);
112 assertOrPanic(bar({}) != null);
113}
114
115fn bar(x: ?void) ?void {
116 if (x) |_| {
117 return {};
118 } else {
119 return null;
120 }
121}
122
123const StructWithOptional = struct {
124 field: ?i32,
125};
126
127var struct_with_optional: StructWithOptional = undefined;
128
129test "unwrap optional which is field of global var" {
130 struct_with_optional.field = null;
131 if (struct_with_optional.field) |payload| {
132 unreachable;
133 }
134 struct_with_optional.field = 1234;
135 if (struct_with_optional.field) |payload| {
136 assertOrPanic(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 assertOrPanic(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 assertOrPanic(opt_type_struct.t != null and opt_type_struct.t.? == u8);
151 }
152}
153
154const StructWithOptionalType = struct {
155 t: ?type,
156};
157
158test "optional pointer to 0 bit type null value at runtime" {
159 const EmptyStruct = struct {};
160 var x: ?*EmptyStruct = null;
161 assertOrPanic(x == null);
162}
test/stage1/behavior/optional.zig created+81
......@@ -0,0 +1,81 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3pub const EmptyStruct = struct {};
4
5test "optional pointer to size zero struct" {
6 var e = EmptyStruct{};
7 var o: ?*EmptyStruct = &e;
8 assertOrPanic(o != null);
9}
10
11test "equality compare nullable pointers" {
12 testNullPtrsEql();
13 comptime testNullPtrsEql();
14}
15
16fn testNullPtrsEql() void {
17 var number: i32 = 1234;
18
19 var x: ?*i32 = null;
20 var y: ?*i32 = null;
21 assertOrPanic(x == y);
22 y = &number;
23 assertOrPanic(x != y);
24 assertOrPanic(x != &number);
25 assertOrPanic(&number != x);
26 x = &number;
27 assertOrPanic(x == y);
28 assertOrPanic(x == &number);
29 assertOrPanic(&number == x);
30}
31
32test "address of unwrap optional" {
33 const S = struct {
34 const Foo = struct {
35 a: i32,
36 };
37
38 var global: ?Foo = null;
39
40 pub fn getFoo() anyerror!*Foo {
41 return &global.?;
42 }
43 };
44 S.global = S.Foo{ .a = 1234 };
45 const foo = S.getFoo() catch unreachable;
46 assertOrPanic(foo.a == 1234);
47}
48
49test "passing an optional integer as a parameter" {
50 const S = struct {
51 fn entry() bool {
52 var x: i32 = 1234;
53 return foo(x);
54 }
55
56 fn foo(x: ?i32) bool {
57 return x.? == 1234;
58 }
59 };
60 assertOrPanic(S.entry());
61 comptime assertOrPanic(S.entry());
62}
63
64test "unwrap function call with optional pointer return value" {
65 const S = struct {
66 fn entry() void {
67 assertOrPanic(foo().?.* == 1234);
68 assertOrPanic(bar() == null);
69 }
70 const global: i32 = 1234;
71 fn foo() ?*const i32 {
72 return &global;
73 }
74 fn bar() ?*i32 {
75 return null;
76 }
77 };
78 S.entry();
79 // TODO https://github.com/ziglang/zig/issues/1901
80 //comptime S.entry();
81}
test/stage1/behavior/pointers.zig created+44
......@@ -0,0 +1,44 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "dereference pointer" {
5 comptime testDerefPtr();
6 testDerefPtr();
7}
8
9fn testDerefPtr() void {
10 var x: i32 = 1234;
11 var y = &x;
12 y.* += 1;
13 assertOrPanic(x == 1235);
14}
15
16test "pointer arithmetic" {
17 var ptr = c"abcd";
18
19 assertOrPanic(ptr[0] == 'a');
20 ptr += 1;
21 assertOrPanic(ptr[0] == 'b');
22 ptr += 1;
23 assertOrPanic(ptr[0] == 'c');
24 ptr += 1;
25 assertOrPanic(ptr[0] == 'd');
26 ptr += 1;
27 assertOrPanic(ptr[0] == 0);
28 ptr -= 1;
29 assertOrPanic(ptr[0] == 'd');
30 ptr -= 1;
31 assertOrPanic(ptr[0] == 'c');
32 ptr -= 1;
33 assertOrPanic(ptr[0] == 'b');
34 ptr -= 1;
35 assertOrPanic(ptr[0] == 'a');
36}
37
38test "double pointer parsing" {
39 comptime assertOrPanic(PtrOf(PtrOf(i32)) == **i32);
40}
41
42fn PtrOf(comptime T: type) type {
43 return *T;
44}
test/stage1/behavior/popcount.zig created+25
......@@ -0,0 +1,25 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "@popCount" {
4 comptime testPopCount();
5 testPopCount();
6}
7
8fn testPopCount() void {
9 {
10 var x: u32 = 0xaa;
11 assertOrPanic(@popCount(x) == 4);
12 }
13 {
14 var x: u32 = 0xaaaaaaaa;
15 assertOrPanic(@popCount(x) == 16);
16 }
17 {
18 var x: i16 = -1;
19 assertOrPanic(@popCount(x) == 16);
20 }
21 comptime {
22 assertOrPanic(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
23 }
24}
25
test/stage1/behavior/ptrcast.zig created+52
......@@ -0,0 +1,52 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "reinterpret bytes as integer with nonzero offset" {
6 testReinterpretBytesAsInteger();
7 comptime testReinterpretBytesAsInteger();
8}
9
10fn testReinterpretBytesAsInteger() void {
11 const bytes = "\x12\x34\x56\x78\xab";
12 const expected = switch (builtin.endian) {
13 builtin.Endian.Little => 0xab785634,
14 builtin.Endian.Big => 0x345678ab,
15 };
16 assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
17}
18
19test "reinterpret bytes of an array into an extern struct" {
20 testReinterpretBytesAsExternStruct();
21 comptime testReinterpretBytesAsExternStruct();
22}
23
24fn testReinterpretBytesAsExternStruct() void {
25 var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
26
27 const S = extern struct {
28 a: u8,
29 b: u16,
30 c: u8,
31 };
32
33 var ptr = @ptrCast(*const S, &bytes);
34 var val = ptr.c;
35 assertOrPanic(val == 5);
36}
37
38test "reinterpret struct field at comptime" {
39 const numLittle = comptime Bytes.init(0x12345678);
40 assertOrPanic(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes));
41}
42
43const Bytes = struct {
44 bytes: [4]u8,
45
46 pub fn init(v: u32) Bytes {
47 var res: Bytes = undefined;
48 @ptrCast(*align(1) u32, &res.bytes).* = v;
49
50 return res;
51 }
52};
test/stage1/behavior/pub_enum/index.zig created+13
......@@ -0,0 +1,13 @@
1const other = @import("other.zig");
2const assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "pub enum" {
5 pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) void {
8 assertOrPanic(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 assertOrPanic(other.size_t(42) == 42);
13}
test/stage1/behavior/pub_enum/other.zig created+6
......@@ -0,0 +1,6 @@
1pub const APubEnum = enum {
2 One,
3 Two,
4 Three,
5};
6pub const size_t = u64;
test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig created+37
......@@ -0,0 +1,37 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4var ok: bool = false;
5test "reference a variable in an if after an if in the 2nd switch prong" {
6 foo(true, Num.Two, false, "aoeu");
7 assertOrPanic(!ok);
8 foo(false, Num.One, false, "aoeu");
9 assertOrPanic(!ok);
10 foo(true, Num.One, false, "aoeu");
11 assertOrPanic(ok);
12}
13
14const Num = enum {
15 One,
16 Two,
17};
18
19fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
20 switch (k) {
21 Num.Two => {},
22 Num.One => {
23 if (c) {
24 const output_path = b;
25
26 if (c2) {}
27
28 a(output_path);
29 }
30 },
31 }
32}
33
34fn a(x: []const u8) void {
35 assertOrPanic(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/stage1/behavior/reflection.zig created+96
......@@ -0,0 +1,96 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: array, pointer, optional, error union type child" {
6 comptime {
7 assertOrPanic(([10]u8).Child == u8);
8 assertOrPanic((*u8).Child == u8);
9 assertOrPanic((anyerror!u8).Payload == u8);
10 assertOrPanic((?u8).Child == u8);
11 }
12}
13
14test "reflection: function return type, var args, and param types" {
15 comptime {
16 assertOrPanic(@typeOf(dummy).ReturnType == i32);
17 assertOrPanic(!@typeOf(dummy).is_var_args);
18 assertOrPanic(@typeOf(dummy_varargs).is_var_args);
19 assertOrPanic(@typeOf(dummy).arg_count == 3);
20 assertOrPanic(@ArgType(@typeOf(dummy), 0) == bool);
21 assertOrPanic(@ArgType(@typeOf(dummy), 1) == i32);
22 assertOrPanic(@ArgType(@typeOf(dummy), 2) == f32);
23 }
24}
25
26fn dummy(a: bool, b: i32, c: f32) i32 {
27 return 1234;
28}
29fn dummy_varargs(args: ...) void {}
30
31test "reflection: struct member types and names" {
32 comptime {
33 assertOrPanic(@memberCount(Foo) == 3);
34
35 assertOrPanic(@memberType(Foo, 0) == i32);
36 assertOrPanic(@memberType(Foo, 1) == bool);
37 assertOrPanic(@memberType(Foo, 2) == void);
38
39 assertOrPanic(mem.eql(u8, @memberName(Foo, 0), "one"));
40 assertOrPanic(mem.eql(u8, @memberName(Foo, 1), "two"));
41 assertOrPanic(mem.eql(u8, @memberName(Foo, 2), "three"));
42 }
43}
44
45test "reflection: enum member types and names" {
46 comptime {
47 assertOrPanic(@memberCount(Bar) == 4);
48
49 assertOrPanic(@memberType(Bar, 0) == void);
50 assertOrPanic(@memberType(Bar, 1) == i32);
51 assertOrPanic(@memberType(Bar, 2) == bool);
52 assertOrPanic(@memberType(Bar, 3) == f64);
53
54 assertOrPanic(mem.eql(u8, @memberName(Bar, 0), "One"));
55 assertOrPanic(mem.eql(u8, @memberName(Bar, 1), "Two"));
56 assertOrPanic(mem.eql(u8, @memberName(Bar, 2), "Three"));
57 assertOrPanic(mem.eql(u8, @memberName(Bar, 3), "Four"));
58 }
59}
60
61test "reflection: @field" {
62 var f = Foo{
63 .one = 42,
64 .two = true,
65 .three = void{},
66 };
67
68 assertOrPanic(f.one == f.one);
69 assertOrPanic(@field(f, "o" ++ "ne") == f.one);
70 assertOrPanic(@field(f, "t" ++ "wo") == f.two);
71 assertOrPanic(@field(f, "th" ++ "ree") == f.three);
72 assertOrPanic(@field(Foo, "const" ++ "ant") == Foo.constant);
73 assertOrPanic(@field(Bar, "O" ++ "ne") == Bar.One);
74 assertOrPanic(@field(Bar, "T" ++ "wo") == Bar.Two);
75 assertOrPanic(@field(Bar, "Th" ++ "ree") == Bar.Three);
76 assertOrPanic(@field(Bar, "F" ++ "our") == Bar.Four);
77 assertOrPanic(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
78 @field(f, "o" ++ "ne") = 4;
79 assertOrPanic(f.one == 4);
80}
81
82const Foo = struct {
83 const constant = 52;
84
85 one: i32,
86 two: bool,
87 three: void,
88};
89
90const Bar = union(enum) {
91 One: void,
92 Two: i32,
93 Three: bool,
94 Four: f64,
95};
96
test/stage1/behavior/sizeof_and_typeof.zig created+69
......@@ -0,0 +1,69 @@
1const builtin = @import("builtin");
2const assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "@sizeOf and @typeOf" {
5 const y: @typeOf(x) = 120;
6 assertOrPanic(@sizeOf(@typeOf(y)) == 2);
7}
8const x: u16 = 13;
9const z: @typeOf(x) = 19;
10
11const A = struct {
12 a: u8,
13 b: u32,
14 c: u8,
15 d: u3,
16 e: u5,
17 f: u16,
18 g: u16,
19};
20
21const P = packed struct {
22 a: u8,
23 b: u32,
24 c: u8,
25 d: u3,
26 e: u5,
27 f: u16,
28 g: u16,
29};
30
31test "@byteOffsetOf" {
32 // Packed structs have fixed memory layout
33 assertOrPanic(@byteOffsetOf(P, "a") == 0);
34 assertOrPanic(@byteOffsetOf(P, "b") == 1);
35 assertOrPanic(@byteOffsetOf(P, "c") == 5);
36 assertOrPanic(@byteOffsetOf(P, "d") == 6);
37 assertOrPanic(@byteOffsetOf(P, "e") == 6);
38 assertOrPanic(@byteOffsetOf(P, "f") == 7);
39 assertOrPanic(@byteOffsetOf(P, "g") == 9);
40
41 // Normal struct fields can be moved/padded
42 var a: A = undefined;
43 assertOrPanic(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
44 assertOrPanic(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
45 assertOrPanic(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
46 assertOrPanic(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
47 assertOrPanic(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
48 assertOrPanic(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
49 assertOrPanic(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
50}
51
52test "@bitOffsetOf" {
53 // Packed structs have fixed memory layout
54 assertOrPanic(@bitOffsetOf(P, "a") == 0);
55 assertOrPanic(@bitOffsetOf(P, "b") == 8);
56 assertOrPanic(@bitOffsetOf(P, "c") == 40);
57 assertOrPanic(@bitOffsetOf(P, "d") == 48);
58 assertOrPanic(@bitOffsetOf(P, "e") == 51);
59 assertOrPanic(@bitOffsetOf(P, "f") == 56);
60 assertOrPanic(@bitOffsetOf(P, "g") == 72);
61
62 assertOrPanic(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
63 assertOrPanic(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
64 assertOrPanic(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
65 assertOrPanic(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
66 assertOrPanic(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
67 assertOrPanic(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
68 assertOrPanic(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
69}
test/stage1/behavior/slice.zig created+40
......@@ -0,0 +1,40 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4const x = @intToPtr([*]i32, 0x1000)[0..0x500];
5const y = x[0x100..];
6test "compile time slice of pointer to hard coded address" {
7 assertOrPanic(@ptrToInt(x.ptr) == 0x1000);
8 assertOrPanic(x.len == 0x500);
9
10 assertOrPanic(@ptrToInt(y.ptr) == 0x1100);
11 assertOrPanic(y.len == 0x400);
12}
13
14test "slice child property" {
15 var array: [5]i32 = undefined;
16 var slice = array[0..];
17 assertOrPanic(@typeOf(slice).Child == i32);
18}
19
20test "runtime safety lets us slice from len..len" {
21 var an_array = []u8{
22 1,
23 2,
24 3,
25 };
26 assertOrPanic(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
27}
28
29fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
30 return a_slice[start..end];
31}
32
33test "implicitly cast array of size 0 to slice" {
34 var msg = []u8{};
35 assertLenIsZero(msg);
36}
37
38fn assertLenIsZero(msg: []const u8) void {
39 assertOrPanic(msg.len == 0);
40}
test/stage1/behavior/struct.zig created+470
......@@ -0,0 +1,470 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const StructWithNoFields = struct {
7 fn add(a: i32, b: i32) i32 {
8 return a + b;
9 }
10};
11const empty_global_instance = StructWithNoFields{};
12
13test "call struct static method" {
14 const result = StructWithNoFields.add(3, 4);
15 assertOrPanic(result == 7);
16}
17
18test "return empty struct instance" {
19 _ = returnEmptyStructInstance();
20}
21fn returnEmptyStructInstance() StructWithNoFields {
22 return empty_global_instance;
23}
24
25const should_be_11 = StructWithNoFields.add(5, 6);
26
27test "invoke static method in global scope" {
28 assertOrPanic(should_be_11 == 11);
29}
30
31test "void struct fields" {
32 const foo = VoidStructFieldsFoo{
33 .a = void{},
34 .b = 1,
35 .c = void{},
36 };
37 assertOrPanic(foo.b == 1);
38 assertOrPanic(@sizeOf(VoidStructFieldsFoo) == 4);
39}
40const VoidStructFieldsFoo = struct {
41 a: void,
42 b: i32,
43 c: void,
44};
45
46test "structs" {
47 var foo: StructFoo = undefined;
48 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
49 foo.a += 1;
50 foo.b = foo.a == 1;
51 testFoo(foo);
52 testMutation(&foo);
53 assertOrPanic(foo.c == 100);
54}
55const StructFoo = struct {
56 a: i32,
57 b: bool,
58 c: f32,
59};
60fn testFoo(foo: StructFoo) void {
61 assertOrPanic(foo.b);
62}
63fn testMutation(foo: *StructFoo) void {
64 foo.c = 100;
65}
66
67const Node = struct {
68 val: Val,
69 next: *Node,
70};
71
72const Val = struct {
73 x: i32,
74};
75
76test "struct point to self" {
77 var root: Node = undefined;
78 root.val.x = 1;
79
80 var node: Node = undefined;
81 node.next = &root;
82 node.val.x = 2;
83
84 root.next = &node;
85
86 assertOrPanic(node.next.next.next.val.x == 1);
87}
88
89test "struct byval assign" {
90 var foo1: StructFoo = undefined;
91 var foo2: StructFoo = undefined;
92
93 foo1.a = 1234;
94 foo2.a = 0;
95 assertOrPanic(foo2.a == 0);
96 foo2 = foo1;
97 assertOrPanic(foo2.a == 1234);
98}
99
100fn structInitializer() void {
101 const val = Val{ .x = 42 };
102 assertOrPanic(val.x == 42);
103}
104
105test "fn call of struct field" {
106 assertOrPanic(callStructField(Foo{ .ptr = aFunc }) == 13);
107}
108
109const Foo = struct {
110 ptr: fn () i32,
111};
112
113fn aFunc() i32 {
114 return 13;
115}
116
117fn callStructField(foo: Foo) i32 {
118 return foo.ptr();
119}
120
121test "store member function in variable" {
122 const instance = MemberFnTestFoo{ .x = 1234 };
123 const memberFn = MemberFnTestFoo.member;
124 const result = memberFn(instance);
125 assertOrPanic(result == 1234);
126}
127const MemberFnTestFoo = struct {
128 x: i32,
129 fn member(foo: MemberFnTestFoo) i32 {
130 return foo.x;
131 }
132};
133
134test "call member function directly" {
135 const instance = MemberFnTestFoo{ .x = 1234 };
136 const result = MemberFnTestFoo.member(instance);
137 assertOrPanic(result == 1234);
138}
139
140test "member functions" {
141 const r = MemberFnRand{ .seed = 1234 };
142 assertOrPanic(r.getSeed() == 1234);
143}
144const MemberFnRand = struct {
145 seed: u32,
146 pub fn getSeed(r: *const MemberFnRand) u32 {
147 return r.seed;
148 }
149};
150
151test "return struct byval from function" {
152 const bar = makeBar(1234, 5678);
153 assertOrPanic(bar.y == 5678);
154}
155const Bar = struct {
156 x: i32,
157 y: i32,
158};
159fn makeBar(x: i32, y: i32) Bar {
160 return Bar{
161 .x = x,
162 .y = y,
163 };
164}
165
166test "empty struct method call" {
167 const es = EmptyStruct{};
168 assertOrPanic(es.method() == 1234);
169}
170const EmptyStruct = struct {
171 fn method(es: *const EmptyStruct) i32 {
172 return 1234;
173 }
174};
175
176test "return empty struct from fn" {
177 _ = testReturnEmptyStructFromFn();
178}
179const EmptyStruct2 = struct {};
180fn testReturnEmptyStructFromFn() EmptyStruct2 {
181 return EmptyStruct2{};
182}
183
184test "pass slice of empty struct to fn" {
185 assertOrPanic(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
186}
187fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
188 return slice.len;
189}
190
191const APackedStruct = packed struct {
192 x: u8,
193 y: u8,
194};
195
196test "packed struct" {
197 var foo = APackedStruct{
198 .x = 1,
199 .y = 2,
200 };
201 foo.y += 1;
202 const four = foo.x + foo.y;
203 assertOrPanic(four == 4);
204}
205
206const BitField1 = packed struct {
207 a: u3,
208 b: u3,
209 c: u2,
210};
211
212const bit_field_1 = BitField1{
213 .a = 1,
214 .b = 2,
215 .c = 3,
216};
217
218test "bit field access" {
219 var data = bit_field_1;
220 assertOrPanic(getA(&data) == 1);
221 assertOrPanic(getB(&data) == 2);
222 assertOrPanic(getC(&data) == 3);
223 comptime assertOrPanic(@sizeOf(BitField1) == 1);
224
225 data.b += 1;
226 assertOrPanic(data.b == 3);
227
228 data.a += 1;
229 assertOrPanic(data.a == 2);
230 assertOrPanic(data.b == 3);
231}
232
233fn getA(data: *const BitField1) u3 {
234 return data.a;
235}
236
237fn getB(data: *const BitField1) u3 {
238 return data.b;
239}
240
241fn getC(data: *const BitField1) u2 {
242 return data.c;
243}
244
245const Foo24Bits = packed struct {
246 field: u24,
247};
248const Foo96Bits = packed struct {
249 a: u24,
250 b: u24,
251 c: u24,
252 d: u24,
253};
254
255test "packed struct 24bits" {
256 comptime {
257 assertOrPanic(@sizeOf(Foo24Bits) == 3);
258 assertOrPanic(@sizeOf(Foo96Bits) == 12);
259 }
260
261 var value = Foo96Bits{
262 .a = 0,
263 .b = 0,
264 .c = 0,
265 .d = 0,
266 };
267 value.a += 1;
268 assertOrPanic(value.a == 1);
269 assertOrPanic(value.b == 0);
270 assertOrPanic(value.c == 0);
271 assertOrPanic(value.d == 0);
272
273 value.b += 1;
274 assertOrPanic(value.a == 1);
275 assertOrPanic(value.b == 1);
276 assertOrPanic(value.c == 0);
277 assertOrPanic(value.d == 0);
278
279 value.c += 1;
280 assertOrPanic(value.a == 1);
281 assertOrPanic(value.b == 1);
282 assertOrPanic(value.c == 1);
283 assertOrPanic(value.d == 0);
284
285 value.d += 1;
286 assertOrPanic(value.a == 1);
287 assertOrPanic(value.b == 1);
288 assertOrPanic(value.c == 1);
289 assertOrPanic(value.d == 1);
290}
291
292const FooArray24Bits = packed struct {
293 a: u16,
294 b: [2]Foo24Bits,
295 c: u16,
296};
297
298test "packed array 24bits" {
299 comptime {
300 assertOrPanic(@sizeOf([9]Foo24Bits) == 9 * 3);
301 assertOrPanic(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
302 }
303
304 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
305 bytes[bytes.len - 1] = 0xaa;
306 const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
307 assertOrPanic(ptr.a == 0);
308 assertOrPanic(ptr.b[0].field == 0);
309 assertOrPanic(ptr.b[1].field == 0);
310 assertOrPanic(ptr.c == 0);
311
312 ptr.a = maxInt(u16);
313 assertOrPanic(ptr.a == maxInt(u16));
314 assertOrPanic(ptr.b[0].field == 0);
315 assertOrPanic(ptr.b[1].field == 0);
316 assertOrPanic(ptr.c == 0);
317
318 ptr.b[0].field = maxInt(u24);
319 assertOrPanic(ptr.a == maxInt(u16));
320 assertOrPanic(ptr.b[0].field == maxInt(u24));
321 assertOrPanic(ptr.b[1].field == 0);
322 assertOrPanic(ptr.c == 0);
323
324 ptr.b[1].field = maxInt(u24);
325 assertOrPanic(ptr.a == maxInt(u16));
326 assertOrPanic(ptr.b[0].field == maxInt(u24));
327 assertOrPanic(ptr.b[1].field == maxInt(u24));
328 assertOrPanic(ptr.c == 0);
329
330 ptr.c = maxInt(u16);
331 assertOrPanic(ptr.a == maxInt(u16));
332 assertOrPanic(ptr.b[0].field == maxInt(u24));
333 assertOrPanic(ptr.b[1].field == maxInt(u24));
334 assertOrPanic(ptr.c == maxInt(u16));
335
336 assertOrPanic(bytes[bytes.len - 1] == 0xaa);
337}
338
339const FooStructAligned = packed struct {
340 a: u8,
341 b: u8,
342};
343
344const FooArrayOfAligned = packed struct {
345 a: [2]FooStructAligned,
346};
347
348test "aligned array of packed struct" {
349 comptime {
350 assertOrPanic(@sizeOf(FooStructAligned) == 2);
351 assertOrPanic(@sizeOf(FooArrayOfAligned) == 2 * 2);
352 }
353
354 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
355 const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
356
357 assertOrPanic(ptr.a[0].a == 0xbb);
358 assertOrPanic(ptr.a[0].b == 0xbb);
359 assertOrPanic(ptr.a[1].a == 0xbb);
360 assertOrPanic(ptr.a[1].b == 0xbb);
361}
362
363test "runtime struct initialization of bitfield" {
364 const s1 = Nibbles{
365 .x = x1,
366 .y = x1,
367 };
368 const s2 = Nibbles{
369 .x = @intCast(u4, x2),
370 .y = @intCast(u4, x2),
371 };
372
373 assertOrPanic(s1.x == x1);
374 assertOrPanic(s1.y == x1);
375 assertOrPanic(s2.x == @intCast(u4, x2));
376 assertOrPanic(s2.y == @intCast(u4, x2));
377}
378
379var x1 = u4(1);
380var x2 = u8(2);
381
382const Nibbles = packed struct {
383 x: u4,
384 y: u4,
385};
386
387const Bitfields = packed struct {
388 f1: u16,
389 f2: u16,
390 f3: u8,
391 f4: u8,
392 f5: u4,
393 f6: u4,
394 f7: u8,
395};
396
397test "native bit field understands endianness" {
398 var all: u64 = 0x7765443322221111;
399 var bytes: [8]u8 = undefined;
400 @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
401 var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
402
403 assertOrPanic(bitfields.f1 == 0x1111);
404 assertOrPanic(bitfields.f2 == 0x2222);
405 assertOrPanic(bitfields.f3 == 0x33);
406 assertOrPanic(bitfields.f4 == 0x44);
407 assertOrPanic(bitfields.f5 == 0x5);
408 assertOrPanic(bitfields.f6 == 0x6);
409 assertOrPanic(bitfields.f7 == 0x77);
410}
411
412test "align 1 field before self referential align 8 field as slice return type" {
413 const result = alloc(Expr);
414 assertOrPanic(result.len == 0);
415}
416
417const Expr = union(enum) {
418 Literal: u8,
419 Question: *Expr,
420};
421
422fn alloc(comptime T: type) []T {
423 return []T{};
424}
425
426test "call method with mutable reference to struct with no fields" {
427 const S = struct {
428 fn doC(s: *const @This()) bool {
429 return true;
430 }
431 fn do(s: *@This()) bool {
432 return true;
433 }
434 };
435
436 var s = S{};
437 assertOrPanic(S.doC(&s));
438 assertOrPanic(s.doC());
439 assertOrPanic(S.do(&s));
440 assertOrPanic(s.do());
441}
442
443test "implicit cast packed struct field to const ptr" {
444 const LevelUpMove = packed struct {
445 move_id: u9,
446 level: u7,
447
448 fn toInt(value: u7) u7 {
449 return value;
450 }
451 };
452
453 var lup: LevelUpMove = undefined;
454 lup.level = 12;
455 const res = LevelUpMove.toInt(lup.level);
456 assertOrPanic(res == 12);
457}
458
459test "pointer to packed struct member in a stack variable" {
460 const S = packed struct {
461 a: u2,
462 b: u2,
463 };
464
465 var s = S{ .a = 2, .b = 0 };
466 var b_ptr = &s.b;
467 assertOrPanic(s.b == 0);
468 b_ptr.* = 2;
469 assertOrPanic(s.b == 2);
470}
test/stage1/behavior/struct_contains_null_ptr_itself.zig created+21
......@@ -0,0 +1,21 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 assertOrPanic(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?*NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
test/stage1/behavior/struct_contains_slice_of_itself.zig created+85
......@@ -0,0 +1,85 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const Node = struct {
4 payload: i32,
5 children: []Node,
6};
7
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
13test "struct contains slice of itself" {
14 var other_nodes = []Node{
15 Node{
16 .payload = 31,
17 .children = []Node{},
18 },
19 Node{
20 .payload = 32,
21 .children = []Node{},
22 },
23 };
24 var nodes = []Node{
25 Node{
26 .payload = 1,
27 .children = []Node{},
28 },
29 Node{
30 .payload = 2,
31 .children = []Node{},
32 },
33 Node{
34 .payload = 3,
35 .children = other_nodes[0..],
36 },
37 };
38 const root = Node{
39 .payload = 1234,
40 .children = nodes[0..],
41 };
42 assertOrPanic(root.payload == 1234);
43 assertOrPanic(root.children[0].payload == 1);
44 assertOrPanic(root.children[1].payload == 2);
45 assertOrPanic(root.children[2].payload == 3);
46 assertOrPanic(root.children[2].children[0].payload == 31);
47 assertOrPanic(root.children[2].children[1].payload == 32);
48}
49
50test "struct contains aligned slice of itself" {
51 var other_nodes = []NodeAligned{
52 NodeAligned{
53 .payload = 31,
54 .children = []NodeAligned{},
55 },
56 NodeAligned{
57 .payload = 32,
58 .children = []NodeAligned{},
59 },
60 };
61 var nodes = []NodeAligned{
62 NodeAligned{
63 .payload = 1,
64 .children = []NodeAligned{},
65 },
66 NodeAligned{
67 .payload = 2,
68 .children = []NodeAligned{},
69 },
70 NodeAligned{
71 .payload = 3,
72 .children = other_nodes[0..],
73 },
74 };
75 const root = NodeAligned{
76 .payload = 1234,
77 .children = nodes[0..],
78 };
79 assertOrPanic(root.payload == 1234);
80 assertOrPanic(root.children[0].payload == 1);
81 assertOrPanic(root.children[1].payload == 2);
82 assertOrPanic(root.children[2].payload == 3);
83 assertOrPanic(root.children[2].children[0].payload == 31);
84 assertOrPanic(root.children[2].children[1].payload == 32);
85}
test/stage1/behavior/switch.zig created+271
......@@ -0,0 +1,271 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "switch with numbers" {
4 testSwitchWithNumbers(13);
5}
6
7fn testSwitchWithNumbers(x: u32) void {
8 const result = switch (x) {
9 1, 2, 3, 4...8 => false,
10 13 => true,
11 else => false,
12 };
13 assertOrPanic(result);
14}
15
16test "switch with all ranges" {
17 assertOrPanic(testSwitchWithAllRanges(50, 3) == 1);
18 assertOrPanic(testSwitchWithAllRanges(101, 0) == 2);
19 assertOrPanic(testSwitchWithAllRanges(300, 5) == 3);
20 assertOrPanic(testSwitchWithAllRanges(301, 6) == 6);
21}
22
23fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
24 return switch (x) {
25 0...100 => 1,
26 101...200 => 2,
27 201...300 => 3,
28 else => y,
29 };
30}
31
32test "implicit comptime switch" {
33 const x = 3 + 4;
34 const result = switch (x) {
35 3 => 10,
36 4 => 11,
37 5, 6 => 12,
38 7, 8 => 13,
39 else => 14,
40 };
41
42 comptime {
43 assertOrPanic(result + 1 == 14);
44 }
45}
46
47test "switch on enum" {
48 const fruit = Fruit.Orange;
49 nonConstSwitchOnEnum(fruit);
50}
51const Fruit = enum {
52 Apple,
53 Orange,
54 Banana,
55};
56fn nonConstSwitchOnEnum(fruit: Fruit) void {
57 switch (fruit) {
58 Fruit.Apple => unreachable,
59 Fruit.Orange => {},
60 Fruit.Banana => unreachable,
61 }
62}
63
64test "switch statement" {
65 nonConstSwitch(SwitchStatmentFoo.C);
66}
67fn nonConstSwitch(foo: SwitchStatmentFoo) void {
68 const val = switch (foo) {
69 SwitchStatmentFoo.A => i32(1),
70 SwitchStatmentFoo.B => 2,
71 SwitchStatmentFoo.C => 3,
72 SwitchStatmentFoo.D => 4,
73 };
74 assertOrPanic(val == 3);
75}
76const SwitchStatmentFoo = enum {
77 A,
78 B,
79 C,
80 D,
81};
82
83test "switch prong with variable" {
84 switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
85 switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
86 switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
87}
88const SwitchProngWithVarEnum = union(enum) {
89 One: i32,
90 Two: f32,
91 Meh: void,
92};
93fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void {
94 switch (a) {
95 SwitchProngWithVarEnum.One => |x| {
96 assertOrPanic(x == 13);
97 },
98 SwitchProngWithVarEnum.Two => |x| {
99 assertOrPanic(x == 13.0);
100 },
101 SwitchProngWithVarEnum.Meh => |x| {
102 const v: void = x;
103 },
104 }
105}
106
107test "switch on enum using pointer capture" {
108 testSwitchEnumPtrCapture();
109 comptime testSwitchEnumPtrCapture();
110}
111
112fn testSwitchEnumPtrCapture() void {
113 var value = SwitchProngWithVarEnum{ .One = 1234 };
114 switch (value) {
115 SwitchProngWithVarEnum.One => |*x| x.* += 1,
116 else => unreachable,
117 }
118 switch (value) {
119 SwitchProngWithVarEnum.One => |x| assertOrPanic(x == 1235),
120 else => unreachable,
121 }
122}
123
124test "switch with multiple expressions" {
125 const x = switch (returnsFive()) {
126 1, 2, 3 => 1,
127 4, 5, 6 => 2,
128 else => i32(3),
129 };
130 assertOrPanic(x == 2);
131}
132fn returnsFive() i32 {
133 return 5;
134}
135
136const Number = union(enum) {
137 One: u64,
138 Two: u8,
139 Three: f32,
140};
141
142const number = Number{ .Three = 1.23 };
143
144fn returnsFalse() bool {
145 switch (number) {
146 Number.One => |x| return x > 1234,
147 Number.Two => |x| return x == 'a',
148 Number.Three => |x| return x > 12.34,
149 }
150}
151test "switch on const enum with var" {
152 assertOrPanic(!returnsFalse());
153}
154
155test "switch on type" {
156 assertOrPanic(trueIfBoolFalseOtherwise(bool));
157 assertOrPanic(!trueIfBoolFalseOtherwise(i32));
158}
159
160fn trueIfBoolFalseOtherwise(comptime T: type) bool {
161 return switch (T) {
162 bool => true,
163 else => false,
164 };
165}
166
167test "switch handles all cases of number" {
168 testSwitchHandleAllCases();
169 comptime testSwitchHandleAllCases();
170}
171
172fn testSwitchHandleAllCases() void {
173 assertOrPanic(testSwitchHandleAllCasesExhaustive(0) == 3);
174 assertOrPanic(testSwitchHandleAllCasesExhaustive(1) == 2);
175 assertOrPanic(testSwitchHandleAllCasesExhaustive(2) == 1);
176 assertOrPanic(testSwitchHandleAllCasesExhaustive(3) == 0);
177
178 assertOrPanic(testSwitchHandleAllCasesRange(100) == 0);
179 assertOrPanic(testSwitchHandleAllCasesRange(200) == 1);
180 assertOrPanic(testSwitchHandleAllCasesRange(201) == 2);
181 assertOrPanic(testSwitchHandleAllCasesRange(202) == 4);
182 assertOrPanic(testSwitchHandleAllCasesRange(230) == 3);
183}
184
185fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
186 return switch (x) {
187 0 => u2(3),
188 1 => 2,
189 2 => 1,
190 3 => 0,
191 };
192}
193
194fn testSwitchHandleAllCasesRange(x: u8) u8 {
195 return switch (x) {
196 0...100 => u8(0),
197 101...200 => 1,
198 201, 203 => 2,
199 202 => 4,
200 204...255 => 3,
201 };
202}
203
204test "switch all prongs unreachable" {
205 testAllProngsUnreachable();
206 comptime testAllProngsUnreachable();
207}
208
209fn testAllProngsUnreachable() void {
210 assertOrPanic(switchWithUnreachable(1) == 2);
211 assertOrPanic(switchWithUnreachable(2) == 10);
212}
213
214fn switchWithUnreachable(x: i32) i32 {
215 while (true) {
216 switch (x) {
217 1 => return 2,
218 2 => break,
219 else => continue,
220 }
221 }
222 return 10;
223}
224
225fn return_a_number() anyerror!i32 {
226 return 1;
227}
228
229test "capture value of switch with all unreachable prongs" {
230 const x = return_a_number() catch |err| switch (err) {
231 else => unreachable,
232 };
233 assertOrPanic(x == 1);
234}
235
236test "switching on booleans" {
237 testSwitchOnBools();
238 comptime testSwitchOnBools();
239}
240
241fn testSwitchOnBools() void {
242 assertOrPanic(testSwitchOnBoolsTrueAndFalse(true) == false);
243 assertOrPanic(testSwitchOnBoolsTrueAndFalse(false) == true);
244
245 assertOrPanic(testSwitchOnBoolsTrueWithElse(true) == false);
246 assertOrPanic(testSwitchOnBoolsTrueWithElse(false) == true);
247
248 assertOrPanic(testSwitchOnBoolsFalseWithElse(true) == false);
249 assertOrPanic(testSwitchOnBoolsFalseWithElse(false) == true);
250}
251
252fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
253 return switch (x) {
254 true => false,
255 false => true,
256 };
257}
258
259fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
260 return switch (x) {
261 true => false,
262 else => true,
263 };
264}
265
266fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
267 return switch (x) {
268 false => true,
269 else => false,
270 };
271}
test/stage1/behavior/switch_prong_err_enum.zig created+30
......@@ -0,0 +1,30 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3var read_count: u64 = 0;
4
5fn readOnce() anyerror!u64 {
6 read_count += 1;
7 return read_count;
8}
9
10const FormValue = union(enum) {
11 Address: u64,
12 Other: bool,
13};
14
15fn doThing(form_id: u64) anyerror!FormValue {
16 return switch (form_id) {
17 17 => FormValue{ .Address = try readOnce() },
18 else => error.InvalidDebugInfo,
19 };
20}
21
22test "switch prong returns error enum" {
23 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| {
25 assertOrPanic(payload == 1);
26 },
27 else => unreachable,
28 }
29 assertOrPanic(read_count == 1);
30}
test/stage1/behavior/switch_prong_implicit_cast.zig created+22
......@@ -0,0 +1,22 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const FormValue = union(enum) {
4 One: void,
5 Two: bool,
6};
7
8fn foo(id: u64) !FormValue {
9 return switch (id) {
10 2 => FormValue{ .Two = true },
11 1 => FormValue{ .One = {} },
12 else => return error.Whatever,
13 };
14}
15
16test "switch prong implicit cast" {
17 const result = switch (foo(2) catch unreachable) {
18 FormValue.One => false,
19 FormValue.Two => |x| x,
20 };
21 assertOrPanic(result);
22}
test/stage1/behavior/syntax.zig created+60
......@@ -0,0 +1,60 @@
1// Test trailing comma syntax
2// zig fmt: off
3
4const struct_trailing_comma = struct { x: i32, y: i32, };
5const struct_no_comma = struct { x: i32, y: i32 };
6const struct_fn_no_comma = struct { fn m() void {} y: i32 };
7
8const enum_no_comma = enum { A, B };
9
10fn container_init() void {
11 const S = struct { x: i32, y: i32 };
12 _ = S { .x = 1, .y = 2 };
13 _ = S { .x = 1, .y = 2, };
14}
15
16fn type_expr_return1() if (true) A {}
17fn type_expr_return2() for (true) |_| A {}
18fn type_expr_return3() while (true) A {}
19fn type_expr_return4() comptime A {}
20
21fn switch_cases(x: i32) void {
22 switch (x) {
23 1,2,3 => {},
24 4,5, => {},
25 6...8, => {},
26 else => {},
27 }
28}
29
30fn switch_prongs(x: i32) void {
31 switch (x) {
32 0 => {},
33 else => {},
34 }
35 switch (x) {
36 0 => {},
37 else => {}
38 }
39}
40
41const fn_no_comma = fn(i32, i32)void;
42const fn_trailing_comma = fn(i32, i32,)void;
43
44fn fn_calls() void {
45 fn add(x: i32, y: i32,) i32 { x + y };
46 _ = add(1, 2);
47 _ = add(1, 2,);
48}
49
50fn asm_lists() void {
51 if (false) { // Build AST but don't analyze
52 asm ("not real assembly"
53 :[a] "x" (x),);
54 asm ("not real assembly"
55 :[a] "x" (->i32),:[a] "x" (1),);
56 asm ("still not real assembly"
57 :::"a","b",);
58 }
59}
60
test/stage1/behavior/this.zig created+35
......@@ -0,0 +1,35 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const module = @This();
4
5fn Point(comptime T: type) type {
6 return struct {
7 const Self = @This();
8 x: T,
9 y: T,
10
11 fn addOne(self: *Self) void {
12 self.x += 1;
13 self.y += 1;
14 }
15 };
16}
17
18fn add(x: i32, y: i32) i32 {
19 return x + y;
20}
21
22test "this refer to module call private fn" {
23 assertOrPanic(module.add(1, 2) == 3);
24}
25
26test "this refer to container" {
27 var pt = Point(i32){
28 .x = 12,
29 .y = 34,
30 };
31 pt.addOne();
32 assertOrPanic(pt.x == 13);
33 assertOrPanic(pt.y == 35);
34}
35
test/stage1/behavior/truncate.zig created+8
......@@ -0,0 +1,8 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "truncate u0 to larger integer allowed and has comptime known result" {
5 var x: u0 = 0;
6 const y = @truncate(u8, x);
7 comptime assertOrPanic(y == 0);
8}
test/stage1/behavior/try.zig created+43
......@@ -0,0 +1,43 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "try on error union" {
4 tryOnErrorUnionImpl();
5 comptime tryOnErrorUnionImpl();
6}
7
8fn tryOnErrorUnionImpl() void {
9 const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
10 error.ItBroke, error.NoMem => 1,
11 error.CrappedOut => i32(2),
12 else => unreachable,
13 };
14 assertOrPanic(x == 11);
15}
16
17fn returnsTen() anyerror!i32 {
18 return 10;
19}
20
21test "try without vars" {
22 const result1 = if (failIfTrue(true)) 1 else |_| i32(2);
23 assertOrPanic(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
26 assertOrPanic(result2 == 1);
27}
28
29fn failIfTrue(ok: bool) anyerror!void {
30 if (ok) {
31 return error.ItBroke;
32 } else {
33 return;
34 }
35}
36
37test "try then not executed with assignment" {
38 if (failIfTrue(true)) {
39 unreachable;
40 } else |err| {
41 assertOrPanic(err == error.ItBroke);
42 }
43}
test/stage1/behavior/type_info.zig created+264
......@@ -0,0 +1,264 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3const TypeInfo = @import("builtin").TypeInfo;
4const TypeId = @import("builtin").TypeId;
5
6test "type info: tag type, void info" {
7 testBasic();
8 comptime testBasic();
9}
10
11fn testBasic() void {
12 assertOrPanic(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 assertOrPanic(TypeId(void_info) == TypeId.Void);
15 assertOrPanic(void_info.Void == {});
16}
17
18test "type info: integer, floating point type info" {
19 testIntFloat();
20 comptime testIntFloat();
21}
22
23fn testIntFloat() void {
24 const u8_info = @typeInfo(u8);
25 assertOrPanic(TypeId(u8_info) == TypeId.Int);
26 assertOrPanic(!u8_info.Int.is_signed);
27 assertOrPanic(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 assertOrPanic(TypeId(f64_info) == TypeId.Float);
31 assertOrPanic(f64_info.Float.bits == 64);
32}
33
34test "type info: pointer type info" {
35 testPointer();
36 comptime testPointer();
37}
38
39fn testPointer() void {
40 const u32_ptr_info = @typeInfo(*u32);
41 assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer);
42 assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
43 assertOrPanic(u32_ptr_info.Pointer.is_const == false);
44 assertOrPanic(u32_ptr_info.Pointer.is_volatile == false);
45 assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(u32));
46 assertOrPanic(u32_ptr_info.Pointer.child == u32);
47}
48
49test "type info: unknown length pointer type info" {
50 testUnknownLenPtr();
51 comptime testUnknownLenPtr();
52}
53
54fn testUnknownLenPtr() void {
55 const u32_ptr_info = @typeInfo([*]const volatile f64);
56 assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer);
57 assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
58 assertOrPanic(u32_ptr_info.Pointer.is_const == true);
59 assertOrPanic(u32_ptr_info.Pointer.is_volatile == true);
60 assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(f64));
61 assertOrPanic(u32_ptr_info.Pointer.child == f64);
62}
63
64test "type info: slice type info" {
65 testSlice();
66 comptime testSlice();
67}
68
69fn testSlice() void {
70 const u32_slice_info = @typeInfo([]u32);
71 assertOrPanic(TypeId(u32_slice_info) == TypeId.Pointer);
72 assertOrPanic(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
73 assertOrPanic(u32_slice_info.Pointer.is_const == false);
74 assertOrPanic(u32_slice_info.Pointer.is_volatile == false);
75 assertOrPanic(u32_slice_info.Pointer.alignment == 4);
76 assertOrPanic(u32_slice_info.Pointer.child == u32);
77}
78
79test "type info: array type info" {
80 testArray();
81 comptime testArray();
82}
83
84fn testArray() void {
85 const arr_info = @typeInfo([42]bool);
86 assertOrPanic(TypeId(arr_info) == TypeId.Array);
87 assertOrPanic(arr_info.Array.len == 42);
88 assertOrPanic(arr_info.Array.child == bool);
89}
90
91test "type info: optional type info" {
92 testOptional();
93 comptime testOptional();
94}
95
96fn testOptional() void {
97 const null_info = @typeInfo(?void);
98 assertOrPanic(TypeId(null_info) == TypeId.Optional);
99 assertOrPanic(null_info.Optional.child == void);
100}
101
102test "type info: promise info" {
103 testPromise();
104 comptime testPromise();
105}
106
107fn testPromise() void {
108 const null_promise_info = @typeInfo(promise);
109 assertOrPanic(TypeId(null_promise_info) == TypeId.Promise);
110 assertOrPanic(null_promise_info.Promise.child == null);
111
112 const promise_info = @typeInfo(promise->usize);
113 assertOrPanic(TypeId(promise_info) == TypeId.Promise);
114 assertOrPanic(promise_info.Promise.child.? == usize);
115}
116
117test "type info: error set, error union info" {
118 testErrorSet();
119 comptime testErrorSet();
120}
121
122fn testErrorSet() void {
123 const TestErrorSet = error{
124 First,
125 Second,
126 Third,
127 };
128
129 const error_set_info = @typeInfo(TestErrorSet);
130 assertOrPanic(TypeId(error_set_info) == TypeId.ErrorSet);
131 assertOrPanic(error_set_info.ErrorSet.errors.len == 3);
132 assertOrPanic(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
133 assertOrPanic(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
134
135 const error_union_info = @typeInfo(TestErrorSet!usize);
136 assertOrPanic(TypeId(error_union_info) == TypeId.ErrorUnion);
137 assertOrPanic(error_union_info.ErrorUnion.error_set == TestErrorSet);
138 assertOrPanic(error_union_info.ErrorUnion.payload == usize);
139}
140
141test "type info: enum info" {
142 testEnum();
143 comptime testEnum();
144}
145
146fn testEnum() void {
147 const Os = enum {
148 Windows,
149 Macos,
150 Linux,
151 FreeBSD,
152 };
153
154 const os_info = @typeInfo(Os);
155 assertOrPanic(TypeId(os_info) == TypeId.Enum);
156 assertOrPanic(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
157 assertOrPanic(os_info.Enum.fields.len == 4);
158 assertOrPanic(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
159 assertOrPanic(os_info.Enum.fields[3].value == 3);
160 assertOrPanic(os_info.Enum.tag_type == u2);
161 assertOrPanic(os_info.Enum.defs.len == 0);
162}
163
164test "type info: union info" {
165 testUnion();
166 comptime testUnion();
167}
168
169fn testUnion() void {
170 const typeinfo_info = @typeInfo(TypeInfo);
171 assertOrPanic(TypeId(typeinfo_info) == TypeId.Union);
172 assertOrPanic(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
173 assertOrPanic(typeinfo_info.Union.tag_type.? == TypeId);
174 assertOrPanic(typeinfo_info.Union.fields.len == 24);
175 assertOrPanic(typeinfo_info.Union.fields[4].enum_field != null);
176 assertOrPanic(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
177 assertOrPanic(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
178 assertOrPanic(typeinfo_info.Union.defs.len == 20);
179
180 const TestNoTagUnion = union {
181 Foo: void,
182 Bar: u32,
183 };
184
185 const notag_union_info = @typeInfo(TestNoTagUnion);
186 assertOrPanic(TypeId(notag_union_info) == TypeId.Union);
187 assertOrPanic(notag_union_info.Union.tag_type == null);
188 assertOrPanic(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
189 assertOrPanic(notag_union_info.Union.fields.len == 2);
190 assertOrPanic(notag_union_info.Union.fields[0].enum_field == null);
191 assertOrPanic(notag_union_info.Union.fields[1].field_type == u32);
192
193 const TestExternUnion = extern union {
194 foo: *c_void,
195 };
196
197 const extern_union_info = @typeInfo(TestExternUnion);
198 assertOrPanic(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
199 assertOrPanic(extern_union_info.Union.tag_type == null);
200 assertOrPanic(extern_union_info.Union.fields[0].enum_field == null);
201 assertOrPanic(extern_union_info.Union.fields[0].field_type == *c_void);
202}
203
204test "type info: struct info" {
205 testStruct();
206 comptime testStruct();
207}
208
209fn testStruct() void {
210 const struct_info = @typeInfo(TestStruct);
211 assertOrPanic(TypeId(struct_info) == TypeId.Struct);
212 assertOrPanic(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
213 assertOrPanic(struct_info.Struct.fields.len == 3);
214 assertOrPanic(struct_info.Struct.fields[1].offset == null);
215 assertOrPanic(struct_info.Struct.fields[2].field_type == *TestStruct);
216 assertOrPanic(struct_info.Struct.defs.len == 2);
217 assertOrPanic(struct_info.Struct.defs[0].is_pub);
218 assertOrPanic(!struct_info.Struct.defs[0].data.Fn.is_extern);
219 assertOrPanic(struct_info.Struct.defs[0].data.Fn.lib_name == null);
220 assertOrPanic(struct_info.Struct.defs[0].data.Fn.return_type == void);
221 assertOrPanic(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
222}
223
224const TestStruct = packed struct {
225 const Self = @This();
226
227 fieldA: usize,
228 fieldB: void,
229 fieldC: *Self,
230
231 pub fn foo(self: *const Self) void {}
232};
233
234test "type info: function type info" {
235 testFunction();
236 comptime testFunction();
237}
238
239fn testFunction() void {
240 const fn_info = @typeInfo(@typeOf(foo));
241 assertOrPanic(TypeId(fn_info) == TypeId.Fn);
242 assertOrPanic(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
243 assertOrPanic(fn_info.Fn.is_generic);
244 assertOrPanic(fn_info.Fn.args.len == 2);
245 assertOrPanic(fn_info.Fn.is_var_args);
246 assertOrPanic(fn_info.Fn.return_type == null);
247 assertOrPanic(fn_info.Fn.async_allocator_type == null);
248
249 const test_instance: TestStruct = undefined;
250 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
251 assertOrPanic(TypeId(bound_fn_info) == TypeId.BoundFn);
252 assertOrPanic(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
253}
254
255fn foo(comptime a: usize, b: bool, args: ...) usize {
256 return 0;
257}
258
259test "typeInfo with comptime parameter in struct fn def" {
260 const S = struct {
261 pub fn func(comptime x: f32) void {}
262 };
263 comptime var info = @typeInfo(S);
264}
test/stage1/behavior/undefined.zig created+69
......@@ -0,0 +1,69 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4fn initStaticArray() [10]i32 {
5 var array: [10]i32 = undefined;
6 array[0] = 1;
7 array[4] = 2;
8 array[7] = 3;
9 array[9] = 4;
10 return array;
11}
12const static_array = initStaticArray();
13test "init static array to undefined" {
14 assertOrPanic(static_array[0] == 1);
15 assertOrPanic(static_array[4] == 2);
16 assertOrPanic(static_array[7] == 3);
17 assertOrPanic(static_array[9] == 4);
18
19 comptime {
20 assertOrPanic(static_array[0] == 1);
21 assertOrPanic(static_array[4] == 2);
22 assertOrPanic(static_array[7] == 3);
23 assertOrPanic(static_array[9] == 4);
24 }
25}
26
27const Foo = struct {
28 x: i32,
29
30 fn setFooXMethod(foo: *Foo) void {
31 foo.x = 3;
32 }
33};
34
35fn setFooX(foo: *Foo) void {
36 foo.x = 2;
37}
38
39test "assign undefined to struct" {
40 comptime {
41 var foo: Foo = undefined;
42 setFooX(&foo);
43 assertOrPanic(foo.x == 2);
44 }
45 {
46 var foo: Foo = undefined;
47 setFooX(&foo);
48 assertOrPanic(foo.x == 2);
49 }
50}
51
52test "assign undefined to struct with method" {
53 comptime {
54 var foo: Foo = undefined;
55 foo.setFooXMethod();
56 assertOrPanic(foo.x == 3);
57 }
58 {
59 var foo: Foo = undefined;
60 foo.setFooXMethod();
61 assertOrPanic(foo.x == 3);
62 }
63}
64
65test "type name of undefined" {
66 const x = undefined;
67 assertOrPanic(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
68}
69
test/stage1/behavior/underscore.zig created+28
......@@ -0,0 +1,28 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "ignore lval with underscore" {
5 _ = false;
6}
7
8test "ignore lval with underscore (for loop)" {
9 for ([]void{}) |_, i| {
10 for ([]void{}) |_, j| {
11 break;
12 }
13 break;
14 }
15}
16
17test "ignore lval with underscore (while loop)" {
18 while (optionalReturnError()) |_| {
19 while (optionalReturnError()) |_| {
20 break;
21 } else |_| {}
22 break;
23 } else |_| {}
24}
25
26fn optionalReturnError() !?u32 {
27 return error.optionalReturnError;
28}
test/stage1/behavior/union.zig created+352
......@@ -0,0 +1,352 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const Value = union(enum) {
4 Int: u64,
5 Array: [9]u8,
6};
7
8const Agg = struct {
9 val1: Value,
10 val2: Value,
11};
12
13const v1 = Value{ .Int = 1234 };
14const v2 = Value{ .Array = []u8{3} ** 9 };
15
16const err = (anyerror!Agg)(Agg{
17 .val1 = v1,
18 .val2 = v2,
19});
20
21const array = []Value{
22 v1,
23 v2,
24 v1,
25 v2,
26};
27
28test "unions embedded in aggregate types" {
29 switch (array[1]) {
30 Value.Array => |arr| assertOrPanic(arr[4] == 3),
31 else => unreachable,
32 }
33 switch ((err catch unreachable).val1) {
34 Value.Int => |x| assertOrPanic(x == 1234),
35 else => unreachable,
36 }
37}
38
39const Foo = union {
40 float: f64,
41 int: i32,
42};
43
44test "basic unions" {
45 var foo = Foo{ .int = 1 };
46 assertOrPanic(foo.int == 1);
47 foo = Foo{ .float = 12.34 };
48 assertOrPanic(foo.float == 12.34);
49}
50
51test "comptime union field access" {
52 comptime {
53 var foo = Foo{ .int = 0 };
54 assertOrPanic(foo.int == 0);
55
56 foo = Foo{ .float = 42.42 };
57 assertOrPanic(foo.float == 42.42);
58 }
59}
60
61test "init union with runtime value" {
62 var foo: Foo = undefined;
63
64 setFloat(&foo, 12.34);
65 assertOrPanic(foo.float == 12.34);
66
67 setInt(&foo, 42);
68 assertOrPanic(foo.int == 42);
69}
70
71fn setFloat(foo: *Foo, x: f64) void {
72 foo.* = Foo{ .float = x };
73}
74
75fn setInt(foo: *Foo, x: i32) void {
76 foo.* = Foo{ .int = x };
77}
78
79const FooExtern = extern union {
80 float: f64,
81 int: i32,
82};
83
84test "basic extern unions" {
85 var foo = FooExtern{ .int = 1 };
86 assertOrPanic(foo.int == 1);
87 foo.float = 12.34;
88 assertOrPanic(foo.float == 12.34);
89}
90
91const Letter = enum {
92 A,
93 B,
94 C,
95};
96const Payload = union(Letter) {
97 A: i32,
98 B: f64,
99 C: bool,
100};
101
102test "union with specified enum tag" {
103 doTest();
104 comptime doTest();
105}
106
107fn doTest() void {
108 assertOrPanic(bar(Payload{ .A = 1234 }) == -10);
109}
110
111fn bar(value: Payload) i32 {
112 assertOrPanic(Letter(value) == Letter.A);
113 return switch (value) {
114 Payload.A => |x| return x - 1244,
115 Payload.B => |x| if (x == 12.34) i32(20) else 21,
116 Payload.C => |x| if (x) i32(30) else 31,
117 };
118}
119
120const MultipleChoice = union(enum(u32)) {
121 A = 20,
122 B = 40,
123 C = 60,
124 D = 1000,
125};
126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;
128 assertOrPanic(x == MultipleChoice.C);
129 assertOrPanic(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130}
131
132const MultipleChoice2 = union(enum(u32)) {
133 Unspecified1: i32,
134 A: f32 = 20,
135 Unspecified2: void,
136 B: bool = 40,
137 Unspecified3: i32,
138 C: i8 = 60,
139 Unspecified4: void,
140 D: void = 1000,
141 Unspecified5: i32,
142};
143
144test "union(enum(u32)) with specified and unspecified tag values" {
145 comptime assertOrPanic(@TagType(@TagType(MultipleChoice2)) == u32);
146 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
147 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
148}
149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
151 assertOrPanic(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
152 assertOrPanic(1123 == switch (x) {
153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,
155 MultipleChoice2.C => |v| i32(1000) + v,
156 MultipleChoice2.D => 4,
157 MultipleChoice2.Unspecified1 => 5,
158 MultipleChoice2.Unspecified2 => 6,
159 MultipleChoice2.Unspecified3 => 7,
160 MultipleChoice2.Unspecified4 => 8,
161 MultipleChoice2.Unspecified5 => 9,
162 });
163}
164
165const ExternPtrOrInt = extern union {
166 ptr: *u8,
167 int: u64,
168};
169test "extern union size" {
170 comptime assertOrPanic(@sizeOf(ExternPtrOrInt) == 8);
171}
172
173const PackedPtrOrInt = packed union {
174 ptr: *u8,
175 int: u64,
176};
177test "extern union size" {
178 comptime assertOrPanic(@sizeOf(PackedPtrOrInt) == 8);
179}
180
181const ZeroBits = union {
182 OnlyField: void,
183};
184test "union with only 1 field which is void should be zero bits" {
185 comptime assertOrPanic(@sizeOf(ZeroBits) == 0);
186}
187
188const TheTag = enum {
189 A,
190 B,
191 C,
192};
193const TheUnion = union(TheTag) {
194 A: i32,
195 B: i32,
196 C: i32,
197};
198test "union field access gives the enum values" {
199 assertOrPanic(TheUnion.A == TheTag.A);
200 assertOrPanic(TheUnion.B == TheTag.B);
201 assertOrPanic(TheUnion.C == TheTag.C);
202}
203
204test "cast union to tag type of union" {
205 testCastUnionToTagType(TheUnion{ .B = 1234 });
206 comptime testCastUnionToTagType(TheUnion{ .B = 1234 });
207}
208
209fn testCastUnionToTagType(x: TheUnion) void {
210 assertOrPanic(TheTag(x) == TheTag.B);
211}
212
213test "cast tag type of union to union" {
214 var x: Value2 = Letter2.B;
215 assertOrPanic(Letter2(x) == Letter2.B);
216}
217const Letter2 = enum {
218 A,
219 B,
220 C,
221};
222const Value2 = union(Letter2) {
223 A: i32,
224 B,
225 C,
226};
227
228test "implicit cast union to its tag type" {
229 var x: Value2 = Letter2.B;
230 assertOrPanic(x == Letter2.B);
231 giveMeLetterB(x);
232}
233fn giveMeLetterB(x: Letter2) void {
234 assertOrPanic(x == Value2.B);
235}
236
237pub const PackThis = union(enum) {
238 Invalid: bool,
239 StringLiteral: u2,
240};
241
242test "constant packed union" {
243 testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }});
244}
245
246fn testConstPackedUnion(expected_tokens: []const PackThis) void {
247 assertOrPanic(expected_tokens[0].StringLiteral == 1);
248}
249
250test "switch on union with only 1 field" {
251 var r: PartialInst = undefined;
252 r = PartialInst.Compiled;
253 switch (r) {
254 PartialInst.Compiled => {
255 var z: PartialInstWithPayload = undefined;
256 z = PartialInstWithPayload{ .Compiled = 1234 };
257 switch (z) {
258 PartialInstWithPayload.Compiled => |x| {
259 assertOrPanic(x == 1234);
260 return;
261 },
262 }
263 },
264 }
265 unreachable;
266}
267
268const PartialInst = union(enum) {
269 Compiled,
270};
271
272const PartialInstWithPayload = union(enum) {
273 Compiled: i32,
274};
275
276test "access a member of tagged union with conflicting enum tag name" {
277 const Bar = union(enum) {
278 A: A,
279 B: B,
280
281 const A = u8;
282 const B = void;
283 };
284
285 comptime assertOrPanic(Bar.A == u8);
286}
287
288test "tagged union initialization with runtime void" {
289 assertOrPanic(testTaggedUnionInit({}));
290}
291
292const TaggedUnionWithAVoid = union(enum) {
293 A,
294 B: i32,
295};
296
297fn testTaggedUnionInit(x: var) bool {
298 const y = TaggedUnionWithAVoid{ .A = x };
299 return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A;
300}
301
302pub const UnionEnumNoPayloads = union(enum) {
303 A,
304 B,
305};
306
307test "tagged union with no payloads" {
308 const a = UnionEnumNoPayloads{ .B = {} };
309 switch (a) {
310 @TagType(UnionEnumNoPayloads).A => @panic("wrong"),
311 @TagType(UnionEnumNoPayloads).B => {},
312 }
313}
314
315test "union with only 1 field casted to its enum type" {
316 const Literal = union(enum) {
317 Number: f64,
318 Bool: bool,
319 };
320
321 const Expr = union(enum) {
322 Literal: Literal,
323 };
324
325 var e = Expr{ .Literal = Literal{ .Bool = true } };
326 const Tag = @TagType(Expr);
327 comptime assertOrPanic(@TagType(Tag) == comptime_int);
328 var t = Tag(e);
329 assertOrPanic(t == Expr.Literal);
330}
331
332test "union with only 1 field casted to its enum type which has enum value specified" {
333 const Literal = union(enum) {
334 Number: f64,
335 Bool: bool,
336 };
337
338 const Tag = enum {
339 Literal = 33,
340 };
341
342 const Expr = union(Tag) {
343 Literal: Literal,
344 };
345
346 var e = Expr{ .Literal = Literal{ .Bool = true } };
347 comptime assertOrPanic(@TagType(Tag) == comptime_int);
348 var t = Tag(e);
349 assertOrPanic(t == Expr.Literal);
350 assertOrPanic(@enumToInt(t) == 33);
351 comptime assertOrPanic(@enumToInt(t) == 33);
352}
test/stage1/behavior/var_args.zig created+84
......@@ -0,0 +1,84 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3fn add(args: ...) i32 {
4 var sum = i32(0);
5 {
6 comptime var i: usize = 0;
7 inline while (i < args.len) : (i += 1) {
8 sum += args[i];
9 }
10 }
11 return sum;
12}
13
14test "add arbitrary args" {
15 assertOrPanic(add(i32(1), i32(2), i32(3), i32(4)) == 10);
16 assertOrPanic(add(i32(1234)) == 1234);
17 assertOrPanic(add() == 0);
18}
19
20fn readFirstVarArg(args: ...) void {
21 const value = args[0];
22}
23
24test "send void arg to var args" {
25 readFirstVarArg({});
26}
27
28test "pass args directly" {
29 assertOrPanic(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
30 assertOrPanic(addSomeStuff(i32(1234)) == 1234);
31 assertOrPanic(addSomeStuff() == 0);
32}
33
34fn addSomeStuff(args: ...) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 assertOrPanic(extraFn(10) == 0);
40 assertOrPanic(extraFn(10, false) == 1);
41 assertOrPanic(extraFn(10, false, true) == 2);
42
43 // TODO issue #313
44 //comptime {
45 // assertOrPanic(extraFn(10) == 0);
46 // assertOrPanic(extraFn(10, false) == 1);
47 // assertOrPanic(extraFn(10, false, true) == 2);
48 //}
49}
50
51fn extraFn(extra: u32, args: ...) usize {
52 if (args.len >= 1) {
53 assertOrPanic(args[0] == false);
54 }
55 if (args.len >= 2) {
56 assertOrPanic(args[1] == true);
57 }
58 return args.len;
59}
60
61const foos = []fn (...) bool{
62 foo1,
63 foo2,
64};
65
66fn foo1(args: ...) bool {
67 return true;
68}
69fn foo2(args: ...) bool {
70 return false;
71}
72
73test "array of var args functions" {
74 assertOrPanic(foos[0]());
75 assertOrPanic(!foos[1]());
76}
77
78test "pass zero length array to var args param" {
79 doNothingWithFirstArg("");
80}
81
82fn doNothingWithFirstArg(args: ...) void {
83 const a = args[0];
84}
test/stage1/behavior/void.zig created+35
......@@ -0,0 +1,35 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9test "compare void with void compile time known" {
10 comptime {
11 const foo = Foo{
12 .a = {},
13 .b = 1,
14 .c = {},
15 };
16 assertOrPanic(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 assertOrPanic(i == j);
24 j += 1;
25 }
26}
27
28fn times(n: usize) []const void {
29 return ([*]void)(undefined)[0..n];
30}
31
32test "void optional" {
33 var x: ?void = {};
34 assertOrPanic(x != null);
35}
test/stage1/behavior/while.zig created+228
......@@ -0,0 +1,228 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "while loop" {
4 var i: i32 = 0;
5 while (i < 4) {
6 i += 1;
7 }
8 assertOrPanic(i == 4);
9 assertOrPanic(whileLoop1() == 1);
10}
11fn whileLoop1() i32 {
12 return whileLoop2();
13}
14fn whileLoop2() i32 {
15 while (true) {
16 return 1;
17 }
18}
19
20test "static eval while" {
21 assertOrPanic(static_eval_while_number == 1);
22}
23const static_eval_while_number = staticWhileLoop1();
24fn staticWhileLoop1() i32 {
25 return whileLoop2();
26}
27fn staticWhileLoop2() i32 {
28 while (true) {
29 return 1;
30 }
31}
32
33test "continue and break" {
34 runContinueAndBreakTest();
35 assertOrPanic(continue_and_break_counter == 8);
36}
37var continue_and_break_counter: i32 = 0;
38fn runContinueAndBreakTest() void {
39 var i: i32 = 0;
40 while (true) {
41 continue_and_break_counter += 2;
42 i += 1;
43 if (i < 4) {
44 continue;
45 }
46 break;
47 }
48 assertOrPanic(i == 4);
49}
50
51test "return with implicit cast from while loop" {
52 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
53}
54fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
55 while (true) {
56 return;
57 }
58}
59
60test "while with continue expression" {
61 var sum: i32 = 0;
62 {
63 var i: i32 = 0;
64 while (i < 10) : (i += 1) {
65 if (i == 5) continue;
66 sum += i;
67 }
68 }
69 assertOrPanic(sum == 40);
70}
71
72test "while with else" {
73 var sum: i32 = 0;
74 var i: i32 = 0;
75 var got_else: i32 = 0;
76 while (i < 10) : (i += 1) {
77 sum += 1;
78 } else {
79 got_else += 1;
80 }
81 assertOrPanic(sum == 10);
82 assertOrPanic(got_else == 1);
83}
84
85test "while with optional as condition" {
86 numbers_left = 10;
87 var sum: i32 = 0;
88 while (getNumberOrNull()) |value| {
89 sum += value;
90 }
91 assertOrPanic(sum == 45);
92}
93
94test "while with optional as condition with else" {
95 numbers_left = 10;
96 var sum: i32 = 0;
97 var got_else: i32 = 0;
98 while (getNumberOrNull()) |value| {
99 sum += value;
100 assertOrPanic(got_else == 0);
101 } else {
102 got_else += 1;
103 }
104 assertOrPanic(sum == 45);
105 assertOrPanic(got_else == 1);
106}
107
108test "while with error union condition" {
109 numbers_left = 10;
110 var sum: i32 = 0;
111 var got_else: i32 = 0;
112 while (getNumberOrErr()) |value| {
113 sum += value;
114 } else |err| {
115 assertOrPanic(err == error.OutOfNumbers);
116 got_else += 1;
117 }
118 assertOrPanic(sum == 45);
119 assertOrPanic(got_else == 1);
120}
121
122var numbers_left: i32 = undefined;
123fn getNumberOrErr() anyerror!i32 {
124 return if (numbers_left == 0) error.OutOfNumbers else x: {
125 numbers_left -= 1;
126 break :x numbers_left;
127 };
128}
129fn getNumberOrNull() ?i32 {
130 return if (numbers_left == 0) null else x: {
131 numbers_left -= 1;
132 break :x numbers_left;
133 };
134}
135
136test "while on optional with else result follow else prong" {
137 const result = while (returnNull()) |value| {
138 break value;
139 } else
140 i32(2);
141 assertOrPanic(result == 2);
142}
143
144test "while on optional with else result follow break prong" {
145 const result = while (returnOptional(10)) |value| {
146 break value;
147 } else
148 i32(2);
149 assertOrPanic(result == 10);
150}
151
152test "while on error union with else result follow else prong" {
153 const result = while (returnError()) |value| {
154 break value;
155 } else |err|
156 i32(2);
157 assertOrPanic(result == 2);
158}
159
160test "while on error union with else result follow break prong" {
161 const result = while (returnSuccess(10)) |value| {
162 break value;
163 } else |err|
164 i32(2);
165 assertOrPanic(result == 10);
166}
167
168test "while on bool with else result follow else prong" {
169 const result = while (returnFalse()) {
170 break i32(10);
171 } else
172 i32(2);
173 assertOrPanic(result == 2);
174}
175
176test "while on bool with else result follow break prong" {
177 const result = while (returnTrue()) {
178 break i32(10);
179 } else
180 i32(2);
181 assertOrPanic(result == 10);
182}
183
184test "break from outer while loop" {
185 testBreakOuter();
186 comptime testBreakOuter();
187}
188
189fn testBreakOuter() void {
190 outer: while (true) {
191 while (true) {
192 break :outer;
193 }
194 }
195}
196
197test "continue outer while loop" {
198 testContinueOuter();
199 comptime testContinueOuter();
200}
201
202fn testContinueOuter() void {
203 var i: usize = 0;
204 outer: while (i < 10) : (i += 1) {
205 while (true) {
206 continue :outer;
207 }
208 }
209}
210
211fn returnNull() ?i32 {
212 return null;
213}
214fn returnOptional(x: i32) ?i32 {
215 return x;
216}
217fn returnError() anyerror!i32 {
218 return error.YouWantedAnError;
219}
220fn returnSuccess(x: i32) anyerror!i32 {
221 return x;
222}
223fn returnFalse() bool {
224 return false;
225}
226fn returnTrue() bool {
227 return true;
228}
test/stage1/behavior/widening.zig created+28
......@@ -0,0 +1,28 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const mem = std.mem;
4
5test "integer widening" {
6 var a: u8 = 250;
7 var b: u16 = a;
8 var c: u32 = b;
9 var d: u64 = c;
10 var e: u64 = d;
11 var f: u128 = e;
12 assertOrPanic(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 assertOrPanic(b == 250);
19}
20
21test "float widening" {
22 var a: f16 = 12.34;
23 var b: f32 = a;
24 var c: f64 = b;
25 var d: f128 = c;
26 assertOrPanic(d == a);
27}
28