authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-21 19:56:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-21 19:56:37-04:00
log78e03c466c6641571adef4bb3931d6cc6f425eb4
tree7e59a9aae51c69eee5414a39a534b43a40f2e903
parent56c08eb3025a622e5d3f5b2b6c704f8dc2cddf47
signature Commit is signed but in an unrecognized format.

simple async function passing test


9 files changed, 355 insertions(+), 319 deletions(-)

src/all_types.hpp+10-1
...@@ -1346,7 +1346,16 @@ struct ZigFn {...@@ -1346,7 +1346,16 @@ struct ZigFn {
1346 Scope *child_scope; // parent is scope for last parameter1346 Scope *child_scope; // parent is scope for last parameter
1347 ScopeBlock *def_scope; // parent is child_scope1347 ScopeBlock *def_scope; // parent is child_scope
1348 Buf symbol_name;1348 Buf symbol_name;
1349 ZigType *type_entry; // function type1349 // This is the function type assuming the function does not suspend.
1350 // Note that for an async function, this can be shared with non-async functions. So the value here
1351 // should only be read for things in common between non-async and async function types.
1352 ZigType *type_entry;
1353 // For normal functions one could use the type_entry->raw_type_ref and type_entry->raw_di_type.
1354 // However for functions that suspend, those values could possibly be their non-suspending equivalents.
1355 // So these values should be preferred.
1356 LLVMTypeRef raw_type_ref;
1357 ZigLLVMDIType *raw_di_type;
1358
1350 ZigType *frame_type; // coro frame type1359 ZigType *frame_type; // coro frame type
1351 // in the case of normal functions this is the implicit return type1360 // in the case of normal functions this is the implicit return type
1352 // in the case of async functions this is the implicit return type according to the1361 // in the case of async functions this is the implicit return type according to the
src/analyze.cpp+15-2
...@@ -3750,7 +3750,7 @@ bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *sour...@@ -3750,7 +3750,7 @@ bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *sour
3750 return true;3750 return true;
3751}3751}
37523752
3753void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_type_node) {3753static void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_type_node) {
3754 ZigType *fn_type = fn_table_entry->type_entry;3754 ZigType *fn_type = fn_table_entry->type_entry;
3755 assert(!fn_type->data.fn.is_generic);3755 assert(!fn_type->data.fn.is_generic);
3756 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;3756 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
...@@ -5850,6 +5850,7 @@ static const ZigTypeId all_type_ids[] = {...@@ -5850,6 +5850,7 @@ static const ZigTypeId all_type_ids[] = {
5850 ZigTypeIdBoundFn,5850 ZigTypeIdBoundFn,
5851 ZigTypeIdArgTuple,5851 ZigTypeIdArgTuple,
5852 ZigTypeIdOpaque,5852 ZigTypeIdOpaque,
5853 ZigTypeIdCoroFrame,
5853 ZigTypeIdVector,5854 ZigTypeIdVector,
5854 ZigTypeIdEnumLiteral,5855 ZigTypeIdEnumLiteral,
5855};5856};
...@@ -7035,7 +7036,13 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {...@@ -7035,7 +7036,13 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
7035}7036}
70367037
7037void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) {7038void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) {
7038 if (fn_type->llvm_di_type != nullptr) return;7039 if (fn_type->llvm_di_type != nullptr) {
7040 if (fn != nullptr) {
7041 fn->raw_type_ref = fn_type->data.fn.raw_type_ref;
7042 fn->raw_di_type = fn_type->data.fn.raw_di_type;
7043 }
7044 return;
7045 }
70397046
7040 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;7047 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
7041 bool first_arg_return = want_first_arg_sret(g, fn_type_id);7048 bool first_arg_return = want_first_arg_sret(g, fn_type_id);
...@@ -7118,6 +7125,12 @@ void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) {...@@ -7118,6 +7125,12 @@ void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) {
7118 for (size_t i = 0; i < gen_param_types.length; i += 1) {7125 for (size_t i = 0; i < gen_param_types.length; i += 1) {
7119 assert(gen_param_types.items[i] != nullptr);7126 assert(gen_param_types.items[i] != nullptr);
7120 }7127 }
7128 if (fn != nullptr) {
7129 fn->raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),
7130 gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
7131 fn->raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
7132 return;
7133 }
7121 fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),7134 fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),
7122 gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);7135 gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
7123 fn_type->llvm_type = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);7136 fn_type->llvm_type = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
src/analyze.hpp-1
...@@ -105,7 +105,6 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v...@@ -105,7 +105,6 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v
105void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max);105void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max);
106106
107void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);107void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
108void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_type_node);
109108
110ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent);109ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent);
111ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent);110ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent);
src/codegen.cpp+12-8
...@@ -499,7 +499,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -499,7 +499,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
499 ZigType *fn_type = fn_table_entry->type_entry;499 ZigType *fn_type = fn_table_entry->type_entry;
500 // Make the raw_type_ref populated500 // Make the raw_type_ref populated
501 resolve_llvm_types_fn(g, fn_type, fn_table_entry);501 resolve_llvm_types_fn(g, fn_type, fn_table_entry);
502 LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref;502 LLVMTypeRef fn_llvm_type = fn_table_entry->raw_type_ref;
503 if (fn_table_entry->body_node == nullptr) {503 if (fn_table_entry->body_node == nullptr) {
504 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));504 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));
505 if (existing_llvm_fn) {505 if (existing_llvm_fn) {
...@@ -521,9 +521,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -521,9 +521,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
521 assert(entry->value->id == TldIdFn);521 assert(entry->value->id == TldIdFn);
522 TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value);522 TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value);
523 // Make the raw_type_ref populated523 // Make the raw_type_ref populated
524 (void)get_llvm_type(g, tld_fn->fn_entry->type_entry);524 resolve_llvm_types_fn(g, tld_fn->fn_entry->type_entry, tld_fn->fn_entry);
525 tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name),525 tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name),
526 tld_fn->fn_entry->type_entry->data.fn.raw_type_ref);526 tld_fn->fn_entry->raw_type_ref);
527 fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value,527 fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value,
528 LLVMPointerType(fn_llvm_type, 0));528 LLVMPointerType(fn_llvm_type, 0));
529 return fn_table_entry->llvm_value;529 return fn_table_entry->llvm_value;
...@@ -683,10 +683,11 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -683,10 +683,11 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
683 unsigned flags = ZigLLVM_DIFlags_StaticMember;683 unsigned flags = ZigLLVM_DIFlags_StaticMember;
684 ZigLLVMDIScope *fn_di_scope = get_di_scope(g, scope->parent);684 ZigLLVMDIScope *fn_di_scope = get_di_scope(g, scope->parent);
685 assert(fn_di_scope != nullptr);685 assert(fn_di_scope != nullptr);
686 assert(fn_table_entry->raw_di_type != nullptr);
686 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,687 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
687 fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",688 fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
688 import->data.structure.root_struct->di_file, line_number,689 import->data.structure.root_struct->di_file, line_number,
689 fn_table_entry->type_entry->data.fn.raw_di_type, is_internal_linkage,690 fn_table_entry->raw_di_type, is_internal_linkage,
690 is_definition, scope_line, flags, is_optimized, nullptr);691 is_definition, scope_line, flags, is_optimized, nullptr);
691692
692 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);693 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
...@@ -3472,10 +3473,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3472,10 +3473,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3472 }3473 }
34733474
3474 gen_param_values.append(result_loc);3475 gen_param_values.append(result_loc);
3475 } else if (first_arg_ret) {3476 } else {
3476 gen_param_values.append(result_loc);3477 if (first_arg_ret) {
3477 } else if (prefix_arg_err_ret_stack) {3478 gen_param_values.append(result_loc);
3478 gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));3479 }
3480 if (prefix_arg_err_ret_stack) {
3481 gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));
3482 }
3479 }3483 }
3480 FnWalk fn_walk = {};3484 FnWalk fn_walk = {};
3481 fn_walk.id = FnWalkIdCall;3485 fn_walk.id = FnWalkIdCall;
std/hash_map.zig+59-58
...@@ -535,17 +535,18 @@ pub fn getAutoEqlFn(comptime K: type) (fn (K, K) bool) {...@@ -535,17 +535,18 @@ pub fn getAutoEqlFn(comptime K: type) (fn (K, K) bool) {
535// TODO improve these hash functions535// TODO improve these hash functions
536pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type) HashInt {536pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type) HashInt {
537 switch (@typeInfo(@typeOf(key))) {537 switch (@typeInfo(@typeOf(key))) {
538 builtin.TypeId.NoReturn,538 .NoReturn,
539 builtin.TypeId.Opaque,539 .Opaque,
540 builtin.TypeId.Undefined,540 .Undefined,
541 builtin.TypeId.ArgTuple,541 .ArgTuple,
542 .Frame,
542 => @compileError("cannot hash this type"),543 => @compileError("cannot hash this type"),
543544
544 builtin.TypeId.Void,545 .Void,
545 builtin.TypeId.Null,546 .Null,
546 => return 0,547 => return 0,
547548
548 builtin.TypeId.Int => |info| {549 .Int => |info| {
549 const unsigned_x = @bitCast(@IntType(false, info.bits), key);550 const unsigned_x = @bitCast(@IntType(false, info.bits), key);
550 if (info.bits <= HashInt.bit_count) {551 if (info.bits <= HashInt.bit_count) {
551 return HashInt(unsigned_x) ^ comptime rng.scalar(HashInt);552 return HashInt(unsigned_x) ^ comptime rng.scalar(HashInt);
...@@ -554,26 +555,26 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type...@@ -554,26 +555,26 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
554 }555 }
555 },556 },
556557
557 builtin.TypeId.Float => |info| {558 .Float => |info| {
558 return autoHash(@bitCast(@IntType(false, info.bits), key), rng, HashInt);559 return autoHash(@bitCast(@IntType(false, info.bits), key), rng, HashInt);
559 },560 },
560 builtin.TypeId.Bool => return autoHash(@boolToInt(key), rng, HashInt),561 .Bool => return autoHash(@boolToInt(key), rng, HashInt),
561 builtin.TypeId.Enum => return autoHash(@enumToInt(key), rng, HashInt),562 .Enum => return autoHash(@enumToInt(key), rng, HashInt),
562 builtin.TypeId.ErrorSet => return autoHash(@errorToInt(key), rng, HashInt),563 .ErrorSet => return autoHash(@errorToInt(key), rng, HashInt),
563 builtin.TypeId.Fn => return autoHash(@ptrToInt(key), rng, HashInt),564 .Fn => return autoHash(@ptrToInt(key), rng, HashInt),
564565
565 builtin.TypeId.BoundFn,566 .BoundFn,
566 builtin.TypeId.ComptimeFloat,567 .ComptimeFloat,
567 builtin.TypeId.ComptimeInt,568 .ComptimeInt,
568 builtin.TypeId.Type,569 .Type,
569 builtin.TypeId.EnumLiteral,570 .EnumLiteral,
570 => return 0,571 => return 0,
571572
572 builtin.TypeId.Pointer => |info| switch (info.size) {573 .Pointer => |info| switch (info.size) {
573 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),574 .One => @compileError("TODO auto hash for single item pointers"),
574 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"),575 .Many => @compileError("TODO auto hash for many item pointers"),
575 builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto hash C pointers"),576 .C => @compileError("TODO auto hash C pointers"),
576 builtin.TypeInfo.Pointer.Size.Slice => {577 .Slice => {
577 const interval = std.math.max(1, key.len / 256);578 const interval = std.math.max(1, key.len / 256);
578 var i: usize = 0;579 var i: usize = 0;
579 var h = comptime rng.scalar(HashInt);580 var h = comptime rng.scalar(HashInt);
...@@ -584,44 +585,44 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type...@@ -584,44 +585,44 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
584 },585 },
585 },586 },
586587
587 builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"),588 .Optional => @compileError("TODO auto hash for optionals"),
588 builtin.TypeId.Array => @compileError("TODO auto hash for arrays"),589 .Array => @compileError("TODO auto hash for arrays"),
589 builtin.TypeId.Vector => @compileError("TODO auto hash for vectors"),590 .Vector => @compileError("TODO auto hash for vectors"),
590 builtin.TypeId.Struct => @compileError("TODO auto hash for structs"),591 .Struct => @compileError("TODO auto hash for structs"),
591 builtin.TypeId.Union => @compileError("TODO auto hash for unions"),592 .Union => @compileError("TODO auto hash for unions"),
592 builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"),593 .ErrorUnion => @compileError("TODO auto hash for unions"),
593 }594 }
594}595}
595596
596pub fn autoEql(a: var, b: @typeOf(a)) bool {597pub fn autoEql(a: var, b: @typeOf(a)) bool {
597 switch (@typeInfo(@typeOf(a))) {598 switch (@typeInfo(@typeOf(a))) {
598 builtin.TypeId.NoReturn,599 .NoReturn,
599 builtin.TypeId.Opaque,600 .Opaque,
600 builtin.TypeId.Undefined,601 .Undefined,
601 builtin.TypeId.ArgTuple,602 .ArgTuple,
602 => @compileError("cannot test equality of this type"),603 => @compileError("cannot test equality of this type"),
603 builtin.TypeId.Void,604 .Void,
604 builtin.TypeId.Null,605 .Null,
605 => return true,606 => return true,
606 builtin.TypeId.Bool,607 .Bool,
607 builtin.TypeId.Int,608 .Int,
608 builtin.TypeId.Float,609 .Float,
609 builtin.TypeId.ComptimeFloat,610 .ComptimeFloat,
610 builtin.TypeId.ComptimeInt,611 .ComptimeInt,
611 builtin.TypeId.EnumLiteral,612 .EnumLiteral,
612 builtin.TypeId.Promise,613 .Promise,
613 builtin.TypeId.Enum,614 .Enum,
614 builtin.TypeId.BoundFn,615 .BoundFn,
615 builtin.TypeId.Fn,616 .Fn,
616 builtin.TypeId.ErrorSet,617 .ErrorSet,
617 builtin.TypeId.Type,618 .Type,
618 => return a == b,619 => return a == b,
619620
620 builtin.TypeId.Pointer => |info| switch (info.size) {621 .Pointer => |info| switch (info.size) {
621 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),622 .One => @compileError("TODO auto eql for single item pointers"),
622 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"),623 .Many => @compileError("TODO auto eql for many item pointers"),
623 builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto eql for C pointers"),624 .C => @compileError("TODO auto eql for C pointers"),
624 builtin.TypeInfo.Pointer.Size.Slice => {625 .Slice => {
625 if (a.len != b.len) return false;626 if (a.len != b.len) return false;
626 for (a) |a_item, i| {627 for (a) |a_item, i| {
627 if (!autoEql(a_item, b[i])) return false;628 if (!autoEql(a_item, b[i])) return false;
...@@ -630,11 +631,11 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {...@@ -630,11 +631,11 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
630 },631 },
631 },632 },
632633
633 builtin.TypeId.Optional => @compileError("TODO auto eql for optionals"),634 .Optional => @compileError("TODO auto eql for optionals"),
634 builtin.TypeId.Array => @compileError("TODO auto eql for arrays"),635 .Array => @compileError("TODO auto eql for arrays"),
635 builtin.TypeId.Struct => @compileError("TODO auto eql for structs"),636 .Struct => @compileError("TODO auto eql for structs"),
636 builtin.TypeId.Union => @compileError("TODO auto eql for unions"),637 .Union => @compileError("TODO auto eql for unions"),
637 builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"),638 .ErrorUnion => @compileError("TODO auto eql for unions"),
638 builtin.TypeId.Vector => @compileError("TODO auto eql for vectors"),639 .Vector => @compileError("TODO auto eql for vectors"),
639 }640 }
640}641}
std/testing.zig+25-24
...@@ -25,35 +25,36 @@ pub fn expectError(expected_error: anyerror, actual_error_union: var) void {...@@ -25,35 +25,36 @@ pub fn expectError(expected_error: anyerror, actual_error_union: var) void {
25/// The types must match exactly.25/// The types must match exactly.
26pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {26pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
27 switch (@typeInfo(@typeOf(actual))) {27 switch (@typeInfo(@typeOf(actual))) {
28 TypeId.NoReturn,28 .NoReturn,
29 TypeId.BoundFn,29 .BoundFn,
30 TypeId.ArgTuple,30 .ArgTuple,
31 TypeId.Opaque,31 .Opaque,
32 .Frame,
32 => @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"),33 => @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"),
3334
34 TypeId.Undefined,35 .Undefined,
35 TypeId.Null,36 .Null,
36 TypeId.Void,37 .Void,
37 => return,38 => return,
3839
39 TypeId.Type,40 .Type,
40 TypeId.Bool,41 .Bool,
41 TypeId.Int,42 .Int,
42 TypeId.Float,43 .Float,
43 TypeId.ComptimeFloat,44 .ComptimeFloat,
44 TypeId.ComptimeInt,45 .ComptimeInt,
45 TypeId.EnumLiteral,46 .EnumLiteral,
46 TypeId.Enum,47 .Enum,
47 TypeId.Fn,48 .Fn,
48 TypeId.Vector,49 .Vector,
49 TypeId.ErrorSet,50 .ErrorSet,
50 => {51 => {
51 if (actual != expected) {52 if (actual != expected) {
52 std.debug.panic("expected {}, found {}", expected, actual);53 std.debug.panic("expected {}, found {}", expected, actual);
53 }54 }
54 },55 },
5556
56 TypeId.Pointer => |pointer| {57 .Pointer => |pointer| {
57 switch (pointer.size) {58 switch (pointer.size) {
58 builtin.TypeInfo.Pointer.Size.One,59 builtin.TypeInfo.Pointer.Size.One,
59 builtin.TypeInfo.Pointer.Size.Many,60 builtin.TypeInfo.Pointer.Size.Many,
...@@ -75,22 +76,22 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {...@@ -75,22 +76,22 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
75 }76 }
76 },77 },
7778
78 TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual),79 .Array => |array| expectEqualSlices(array.child, &expected, &actual),
7980
80 TypeId.Struct => |structType| {81 .Struct => |structType| {
81 inline for (structType.fields) |field| {82 inline for (structType.fields) |field| {
82 expectEqual(@field(expected, field.name), @field(actual, field.name));83 expectEqual(@field(expected, field.name), @field(actual, field.name));
83 }84 }
84 },85 },
8586
86 TypeId.Union => |union_info| {87 .Union => |union_info| {
87 if (union_info.tag_type == null) {88 if (union_info.tag_type == null) {
88 @compileError("Unable to compare untagged union values");89 @compileError("Unable to compare untagged union values");
89 }90 }
90 @compileError("TODO implement testing.expectEqual for tagged unions");91 @compileError("TODO implement testing.expectEqual for tagged unions");
91 },92 },
9293
93 TypeId.Optional => {94 .Optional => {
94 if (expected) |expected_payload| {95 if (expected) |expected_payload| {
95 if (actual) |actual_payload| {96 if (actual) |actual_payload| {
96 expectEqual(expected_payload, actual_payload);97 expectEqual(expected_payload, actual_payload);
...@@ -104,7 +105,7 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {...@@ -104,7 +105,7 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
104 }105 }
105 },106 },
106107
107 TypeId.ErrorUnion => {108 .ErrorUnion => {
108 if (expected) |expected_payload| {109 if (expected) |expected_payload| {
109 if (actual) |actual_payload| {110 if (actual) |actual_payload| {
110 expectEqual(expected_payload, actual_payload);111 expectEqual(expected_payload, actual_payload);
test/stage1/behavior.zig+1-1
...@@ -43,7 +43,7 @@ comptime {...@@ -43,7 +43,7 @@ comptime {
43 _ = @import("behavior/cast.zig");43 _ = @import("behavior/cast.zig");
44 _ = @import("behavior/const_slice_child.zig");44 _ = @import("behavior/const_slice_child.zig");
45 //_ = @import("behavior/coroutine_await_struct.zig");45 //_ = @import("behavior/coroutine_await_struct.zig");
46 //_ = @import("behavior/coroutines.zig");46 _ = @import("behavior/coroutines.zig");
47 _ = @import("behavior/defer.zig");47 _ = @import("behavior/defer.zig");
48 _ = @import("behavior/enum.zig");48 _ = @import("behavior/enum.zig");
49 _ = @import("behavior/enum_with_members.zig");49 _ = @import("behavior/enum_with_members.zig");
test/stage1/behavior/coroutines.zig+232-223
...@@ -1,236 +1,245 @@...@@ -1,236 +1,245 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const allocator = std.heap.direct_allocator;
54
6var x: i32 = 1;5var x: i32 = 1;
76
8test "create a coroutine and cancel it" {7test "simple coroutine suspend" {
9 const p = try async<allocator> simpleAsyncFn();8 const p = async simpleAsyncFn();
10 comptime expect(@typeOf(p) == promise->void);
11 cancel p;
12 expect(x == 2);9 expect(x == 2);
13}10}
14async fn simpleAsyncFn() void {11fn simpleAsyncFn() void {
15 x += 1;12 x += 1;
16 suspend;13 suspend;
17 x += 1;14 x += 1;
18}15}
1916
20test "coroutine suspend, resume, cancel" {17//test "create a coroutine and cancel it" {
21 seq('a');18// const p = try async<allocator> simpleAsyncFn();
22 const p = try async<allocator> testAsyncSeq();19// comptime expect(@typeOf(p) == promise->void);
23 seq('c');20// cancel p;
24 resume p;21// expect(x == 2);
25 seq('f');22//}
26 cancel p;23//async fn simpleAsyncFn() void {
27 seq('g');24// x += 1;
2825// suspend;
29 expect(std.mem.eql(u8, points, "abcdefg"));26// x += 1;
30}27//}
31async fn testAsyncSeq() void {28//
32 defer seq('e');29//test "coroutine suspend, resume, cancel" {
3330// seq('a');
34 seq('b');31// const p = try async<allocator> testAsyncSeq();
35 suspend;32// seq('c');
36 seq('d');33// resume p;
37}34// seq('f');
38var points = [_]u8{0} ** "abcdefg".len;35// cancel p;
39var index: usize = 0;36// seq('g');
4037//
41fn seq(c: u8) void {38// expect(std.mem.eql(u8, points, "abcdefg"));
42 points[index] = c;39//}
43 index += 1;40//async fn testAsyncSeq() void {
44}41// defer seq('e');
4542//
46test "coroutine suspend with block" {43// seq('b');
47 const p = try async<allocator> testSuspendBlock();44// suspend;
48 std.testing.expect(!result);45// seq('d');
49 resume a_promise;46//}
50 std.testing.expect(result);47//var points = [_]u8{0} ** "abcdefg".len;
51 cancel p;48//var index: usize = 0;
52}49//
5350//fn seq(c: u8) void {
54var a_promise: promise = undefined;51// points[index] = c;
55var result = false;52// index += 1;
56async fn testSuspendBlock() void {53//}
57 suspend {54//
58 comptime expect(@typeOf(@handle()) == promise->void);55//test "coroutine suspend with block" {
59 a_promise = @handle();56// const p = try async<allocator> testSuspendBlock();
60 }57// std.testing.expect(!result);
6158// resume a_promise;
62 //Test to make sure that @handle() works as advertised (issue #1296)59// std.testing.expect(result);
63 //var our_handle: promise = @handle();60// cancel p;
64 expect(a_promise == @handle());61//}
6562//
66 result = true;63//var a_promise: promise = undefined;
67}64//var result = false;
6865//async fn testSuspendBlock() void {
69var await_a_promise: promise = undefined;66// suspend {
70var await_final_result: i32 = 0;67// comptime expect(@typeOf(@handle()) == promise->void);
7168// a_promise = @handle();
72test "coroutine await" {69// }
73 await_seq('a');70//
74 const p = async<allocator> await_amain() catch unreachable;71// //Test to make sure that @handle() works as advertised (issue #1296)
75 await_seq('f');72// //var our_handle: promise = @handle();
76 resume await_a_promise;73// expect(a_promise == @handle());
77 await_seq('i');74//
78 expect(await_final_result == 1234);75// result = true;
79 expect(std.mem.eql(u8, await_points, "abcdefghi"));76//}
80}77//
81async fn await_amain() void {78//var await_a_promise: promise = undefined;
82 await_seq('b');79//var await_final_result: i32 = 0;
83 const p = async await_another() catch unreachable;80//
84 await_seq('e');81//test "coroutine await" {
85 await_final_result = await p;82// await_seq('a');
86 await_seq('h');83// const p = async<allocator> await_amain() catch unreachable;
87}84// await_seq('f');
88async fn await_another() i32 {85// resume await_a_promise;
89 await_seq('c');86// await_seq('i');
90 suspend {87// expect(await_final_result == 1234);
91 await_seq('d');88// expect(std.mem.eql(u8, await_points, "abcdefghi"));
92 await_a_promise = @handle();89//}
93 }90//async fn await_amain() void {
94 await_seq('g');91// await_seq('b');
95 return 1234;92// const p = async await_another() catch unreachable;
96}93// await_seq('e');
9794// await_final_result = await p;
98var await_points = [_]u8{0} ** "abcdefghi".len;95// await_seq('h');
99var await_seq_index: usize = 0;96//}
10097//async fn await_another() i32 {
101fn await_seq(c: u8) void {98// await_seq('c');
102 await_points[await_seq_index] = c;99// suspend {
103 await_seq_index += 1;100// await_seq('d');
104}101// await_a_promise = @handle();
105102// }
106var early_final_result: i32 = 0;103// await_seq('g');
107104// return 1234;
108test "coroutine await early return" {105//}
109 early_seq('a');106//
110 const p = async<allocator> early_amain() catch @panic("out of memory");107//var await_points = [_]u8{0} ** "abcdefghi".len;
111 early_seq('f');108//var await_seq_index: usize = 0;
112 expect(early_final_result == 1234);109//
113 expect(std.mem.eql(u8, early_points, "abcdef"));110//fn await_seq(c: u8) void {
114}111// await_points[await_seq_index] = c;
115async fn early_amain() void {112// await_seq_index += 1;
116 early_seq('b');113//}
117 const p = async early_another() catch @panic("out of memory");114//
118 early_seq('d');115//var early_final_result: i32 = 0;
119 early_final_result = await p;116//
120 early_seq('e');117//test "coroutine await early return" {
121}118// early_seq('a');
122async fn early_another() i32 {119// const p = async<allocator> early_amain() catch @panic("out of memory");
123 early_seq('c');120// early_seq('f');
124 return 1234;121// expect(early_final_result == 1234);
125}122// expect(std.mem.eql(u8, early_points, "abcdef"));
126123//}
127var early_points = [_]u8{0} ** "abcdef".len;124//async fn early_amain() void {
128var early_seq_index: usize = 0;125// early_seq('b');
129126// const p = async early_another() catch @panic("out of memory");
130fn early_seq(c: u8) void {127// early_seq('d');
131 early_points[early_seq_index] = c;128// early_final_result = await p;
132 early_seq_index += 1;129// early_seq('e');
133}130//}
134131//async fn early_another() i32 {
135test "coro allocation failure" {132// early_seq('c');
136 var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);133// return 1234;
137 if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) {134//}
138 @panic("expected allocation failure");135//
139 } else |err| switch (err) {136//var early_points = [_]u8{0} ** "abcdef".len;
140 error.OutOfMemory => {},137//var early_seq_index: usize = 0;
141 }138//
142}139//fn early_seq(c: u8) void {
143async fn asyncFuncThatNeverGetsRun() void {140// early_points[early_seq_index] = c;
144 @panic("coro frame allocation should fail");141// early_seq_index += 1;
145}142//}
146143//
147test "async function with dot syntax" {144//test "coro allocation failure" {
148 const S = struct {145// var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);
149 var y: i32 = 1;146// if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) {
150 async fn foo() void {147// @panic("expected allocation failure");
151 y += 1;148// } else |err| switch (err) {
152 suspend;149// error.OutOfMemory => {},
153 }150// }
154 };151//}
155 const p = try async<allocator> S.foo();152//async fn asyncFuncThatNeverGetsRun() void {
156 cancel p;153// @panic("coro frame allocation should fail");
157 expect(S.y == 2);154//}
158}155//
159156//test "async function with dot syntax" {
160test "async fn pointer in a struct field" {157// const S = struct {
161 var data: i32 = 1;158// var y: i32 = 1;
162 const Foo = struct {159// async fn foo() void {
163 bar: async<*std.mem.Allocator> fn (*i32) void,160// y += 1;
164 };161// suspend;
165 var foo = Foo{ .bar = simpleAsyncFn2 };162// }
166 const p = (async<allocator> foo.bar(&data)) catch unreachable;163// };
167 expect(data == 2);164// const p = try async<allocator> S.foo();
168 cancel p;165// cancel p;
169 expect(data == 4);166// expect(S.y == 2);
170}167//}
171async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {168//
172 defer y.* += 2;169//test "async fn pointer in a struct field" {
173 y.* += 1;170// var data: i32 = 1;
174 suspend;171// const Foo = struct {
175}172// bar: async<*std.mem.Allocator> fn (*i32) void,
176173// };
177test "async fn with inferred error set" {174// var foo = Foo{ .bar = simpleAsyncFn2 };
178 const p = (async<allocator> failing()) catch unreachable;175// const p = (async<allocator> foo.bar(&data)) catch unreachable;
179 resume p;176// expect(data == 2);
180 cancel p;177// cancel p;
181}178// expect(data == 4);
182179//}
183async fn failing() !void {180//async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
184 suspend;181// defer y.* += 2;
185 return error.Fail;182// y.* += 1;
186}183// suspend;
187184//}
188test "error return trace across suspend points - early return" {185//
189 const p = nonFailing();186//test "async fn with inferred error set" {
190 resume p;187// const p = (async<allocator> failing()) catch unreachable;
191 const p2 = try async<allocator> printTrace(p);188// resume p;
192 cancel p2;189// cancel p;
193}190//}
194191//
195test "error return trace across suspend points - async return" {192//async fn failing() !void {
196 const p = nonFailing();193// suspend;
197 const p2 = try async<std.debug.global_allocator> printTrace(p);194// return error.Fail;
198 resume p;195//}
199 cancel p2;196//
200}197//test "error return trace across suspend points - early return" {
201198// const p = nonFailing();
202fn nonFailing() (promise->anyerror!void) {199// resume p;
203 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;200// const p2 = try async<allocator> printTrace(p);
204}201// cancel p2;
205async fn suspendThenFail() anyerror!void {202//}
206 suspend;203//
207 return error.Fail;204//test "error return trace across suspend points - async return" {
208}205// const p = nonFailing();
209async fn printTrace(p: promise->(anyerror!void)) void {206// const p2 = try async<std.debug.global_allocator> printTrace(p);
210 (await p) catch |e| {207// resume p;
211 std.testing.expect(e == error.Fail);208// cancel p2;
212 if (@errorReturnTrace()) |trace| {209//}
213 expect(trace.index == 1);210//
214 } else switch (builtin.mode) {211//fn nonFailing() (promise->anyerror!void) {
215 builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),212// return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
216 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},213//}
217 }214//async fn suspendThenFail() anyerror!void {
218 };215// suspend;
219}216// return error.Fail;
220217//}
221test "break from suspend" {218//async fn printTrace(p: promise->(anyerror!void)) void {
222 var buf: [500]u8 = undefined;219// (await p) catch |e| {
223 var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;220// std.testing.expect(e == error.Fail);
224 var my_result: i32 = 1;221// if (@errorReturnTrace()) |trace| {
225 const p = try async<a> testBreakFromSuspend(&my_result);222// expect(trace.index == 1);
226 cancel p;223// } else switch (builtin.mode) {
227 std.testing.expect(my_result == 2);224// builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
228}225// builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
229async fn testBreakFromSuspend(my_result: *i32) void {226// }
230 suspend {227// };
231 resume @handle();228//}
232 }229//
233 my_result.* += 1;230//test "break from suspend" {
234 suspend;231// var buf: [500]u8 = undefined;
235 my_result.* += 1;232// var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
236}233// var my_result: i32 = 1;
234// const p = try async<a> testBreakFromSuspend(&my_result);
235// cancel p;
236// std.testing.expect(my_result == 2);
237//}
238//async fn testBreakFromSuspend(my_result: *i32) void {
239// suspend {
240// resume @handle();
241// }
242// my_result.* += 1;
243// suspend;
244// my_result.* += 1;
245//}
test/stage1/behavior/type_info.zig+1-1
...@@ -177,7 +177,7 @@ fn testUnion() void {...@@ -177,7 +177,7 @@ fn testUnion() void {
177 expect(TypeId(typeinfo_info) == TypeId.Union);177 expect(TypeId(typeinfo_info) == TypeId.Union);
178 expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);178 expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
179 expect(typeinfo_info.Union.tag_type.? == TypeId);179 expect(typeinfo_info.Union.tag_type.? == TypeId);
180 expect(typeinfo_info.Union.fields.len == 24);180 expect(typeinfo_info.Union.fields.len == 25);
181 expect(typeinfo_info.Union.fields[4].enum_field != null);181 expect(typeinfo_info.Union.fields[4].enum_field != null);
182 expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);182 expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
183 expect(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));183 expect(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));