authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-31 01:51:15-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-31 01:51:31-05:00
log5161d70620342749b1995fdaabb39220654cc941
treeba940c1a85386f1866cd75aab67809b4c0c95755
parent40ca39d3d5a556e3b5d7298e3a5182f4351bdd17

*WIP* error sets


14 files changed, 949 insertions(+), 499 deletions(-)

doc/langref.html.in+8-8
......@@ -1281,7 +1281,7 @@ const ptr = &amp;x;
12811281 <pre><code>x() x[] x.y
12821282!x -x -%x ~x *x &amp;x ?x %x ??x
12831283x{}
1284* / % ** *%
1284! * / % ** *%
12851285+ - ++ +% -%
12861286&lt;&lt; &gt;&gt;
12871287&amp;
......@@ -5566,14 +5566,12 @@ fn readU32Be() u32 {}
55665566 {#header_open|Grammar#}
55675567 <pre><code class="nohighlight">Root = many(TopLevelItem) EOF
55685568
5569TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl
5569TopLevelItem = CompTimeExpression(Block) | TopLevelDecl | TestDecl
55705570
55715571TestDecl = "test" String Block
55725572
55735573TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl)
55745574
5575ErrorValueDecl = "error" Symbol ";"
5576
55775575GlobalVarDecl = option("export") VariableDeclaration ";"
55785576
55795577LocalVarDecl = option("comptime") VariableDeclaration
......@@ -5588,7 +5586,7 @@ UseDecl = "use" Expression ";"
55885586
55895587ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
55905588
5591FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr
5589FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
55925590
55935591FnDef = option("inline" | "export") FnProto Block
55945592
......@@ -5682,7 +5680,7 @@ MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression |
56825680
56835681CurlySuffixExpression = TypeExpr option(ContainerInitExpression)
56845682
5685MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
5683MultiplyOperator = "!" | "*" | "/" | "%" | "**" | "*%"
56865684
56875685PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
56885686
......@@ -5702,9 +5700,9 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
57025700
57035701StructLiteralField = "." Symbol "=" Expression
57045702
5705PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "??" | "-%" | "try"
5703PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try"
57065704
5707PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl | ("continue" option(":" Symbol))
5705PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
57085706
57095707ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr
57105708
......@@ -5712,6 +5710,8 @@ GroupedExpression = "(" Expression ")"
57125710
57135711KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable"
57145712
5713ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
5714
57155715ContainerDecl = option("extern" | "packed")
57165716 ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
57175717 "{" many(ContainerMember) "}"</code></pre>
src/all_types.hpp+41-19
......@@ -236,7 +236,7 @@ struct ConstExprValue {
236236 TypeTableEntry *x_type;
237237 ConstExprValue *x_maybe;
238238 ConstErrValue x_err_union;
239 ErrorTableEntry *x_pure_err;
239 ErrorTableEntry *x_err_set;
240240 BigInt x_enum_tag;
241241 ConstStructValue x_struct;
242242 ConstUnionValue x_union;
......@@ -353,7 +353,6 @@ enum NodeType {
353353 NodeTypeReturnExpr,
354354 NodeTypeDefer,
355355 NodeTypeVariableDeclaration,
356 NodeTypeErrorValueDecl,
357356 NodeTypeTestDecl,
358357 NodeTypeBinOpExpr,
359358 NodeTypeUnwrapErrorExpr,
......@@ -393,6 +392,7 @@ enum NodeType {
393392 NodeTypeVarLiteral,
394393 NodeTypeIfErrorExpr,
395394 NodeTypeTestExpr,
395 NodeTypeErrorSetDecl,
396396};
397397
398398struct AstNodeRoot {
......@@ -424,6 +424,8 @@ struct AstNodeFnProto {
424424 AstNode *align_expr;
425425 // populated if the "section(S)" is present
426426 AstNode *section_expr;
427
428 bool auto_err_set;
427429};
428430
429431struct AstNodeFnDef {
......@@ -486,12 +488,6 @@ struct AstNodeVariableDeclaration {
486488 AstNode *section_expr;
487489};
488490
489struct AstNodeErrorValueDecl {
490 Buf *name;
491
492 ErrorTableEntry *err;
493};
494
495491struct AstNodeTestDecl {
496492 Buf *name;
497493
......@@ -540,6 +536,7 @@ enum BinOpType {
540536 BinOpTypeUnwrapMaybe,
541537 BinOpTypeArrayCat,
542538 BinOpTypeArrayMult,
539 BinOpTypeErrorUnion,
543540};
544541
545542struct AstNodeBinOpExpr {
......@@ -595,7 +592,6 @@ enum PrefixOp {
595592 PrefixOpNegationWrap,
596593 PrefixOpDereference,
597594 PrefixOpMaybe,
598 PrefixOpError,
599595 PrefixOpUnwrapMaybe,
600596};
601597
......@@ -762,6 +758,10 @@ struct AstNodeContainerDecl {
762758 bool auto_enum; // union(enum)
763759};
764760
761struct AstNodeErrorSetDecl {
762 ZigList<AstNode *> decls;
763};
764
765765struct AstNodeStructField {
766766 VisibMod visib_mod;
767767 Buf *name;
......@@ -858,7 +858,6 @@ struct AstNode {
858858 AstNodeReturnExpr return_expr;
859859 AstNodeDefer defer;
860860 AstNodeVariableDeclaration variable_declaration;
861 AstNodeErrorValueDecl error_value_decl;
862861 AstNodeTestDecl test_decl;
863862 AstNodeBinOpExpr bin_op_expr;
864863 AstNodeCatchExpr unwrap_err_expr;
......@@ -899,6 +898,7 @@ struct AstNode {
899898 AstNodeArrayType array_type;
900899 AstNodeErrorType error_type;
901900 AstNodeVarLiteral var_literal;
901 AstNodeErrorSetDecl err_set_decl;
902902 } data;
903903};
904904
......@@ -993,8 +993,15 @@ struct TypeTableEntryMaybe {
993993 TypeTableEntry *child_type;
994994};
995995
996struct TypeTableEntryError {
997 TypeTableEntry *child_type;
996struct TypeTableEntryErrorUnion {
997 TypeTableEntry *err_set_type;
998 TypeTableEntry *payload_type;
999};
1000
1001struct TypeTableEntryErrorSet {
1002 uint32_t err_count;
1003 ErrorTableEntry **errors;
1004 FnTableEntry *infer_fn;
9981005};
9991006
10001007struct TypeTableEntryEnum {
......@@ -1097,7 +1104,7 @@ enum TypeTableEntryId {
10971104 TypeTableEntryIdNullLit,
10981105 TypeTableEntryIdMaybe,
10991106 TypeTableEntryIdErrorUnion,
1100 TypeTableEntryIdPureError,
1107 TypeTableEntryIdErrorSet,
11011108 TypeTableEntryIdEnum,
11021109 TypeTableEntryIdUnion,
11031110 TypeTableEntryIdFn,
......@@ -1126,7 +1133,8 @@ struct TypeTableEntry {
11261133 TypeTableEntryArray array;
11271134 TypeTableEntryStruct structure;
11281135 TypeTableEntryMaybe maybe;
1129 TypeTableEntryError error;
1136 TypeTableEntryErrorUnion error_union;
1137 TypeTableEntryErrorSet error_set;
11301138 TypeTableEntryEnum enumeration;
11311139 TypeTableEntryUnion unionation;
11321140 TypeTableEntryFn fn;
......@@ -1136,7 +1144,6 @@ struct TypeTableEntry {
11361144 // use these fields to make sure we don't duplicate type table entries for the same type
11371145 TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const]
11381146 TypeTableEntry *maybe_parent;
1139 TypeTableEntry *error_parent;
11401147 // If we generate a constant name value for this type, we memoize it here.
11411148 // The type of this is array
11421149 ConstExprValue *cached_const_name_val;
......@@ -1340,6 +1347,10 @@ struct TypeId {
13401347 bool is_signed;
13411348 uint32_t bit_count;
13421349 } integer;
1350 struct {
1351 TypeTableEntry *err_set_type;
1352 TypeTableEntry *payload_type;
1353 } error_union;
13431354 } data;
13441355};
13451356
......@@ -1481,7 +1492,7 @@ struct CodeGen {
14811492 TypeTableEntry *entry_undef;
14821493 TypeTableEntry *entry_null;
14831494 TypeTableEntry *entry_var;
1484 TypeTableEntry *entry_pure_error;
1495 TypeTableEntry *entry_global_error_set;
14851496 TypeTableEntry *entry_arg_tuple;
14861497 } builtin_types;
14871498
......@@ -1570,7 +1581,6 @@ struct CodeGen {
15701581 LLVMValueRef return_address_fn_val;
15711582 LLVMValueRef frame_address_fn_val;
15721583 bool error_during_imports;
1573 TypeTableEntry *err_tag_type;
15741584
15751585 const char **clang_argv;
15761586 size_t clang_argv_len;
......@@ -1584,7 +1594,9 @@ struct CodeGen {
15841594
15851595 bool each_lib_rpath;
15861596
1587 ZigList<AstNode *> error_decls;
1597 TypeTableEntry *err_tag_type;
1598 ZigList<ZigLLVMDIEnumerator *> err_enumerators;
1599 ZigList<ErrorTableEntry *> errors_by_index;
15881600 bool generate_error_name_table;
15891601 LLVMValueRef err_name_table;
15901602 size_t largest_err_name_len;
......@@ -1617,6 +1629,8 @@ struct CodeGen {
16171629 TypeTableEntry *align_amt_type;
16181630 TypeTableEntry *stack_trace_type;
16191631 TypeTableEntry *ptr_to_stack_trace_type;
1632
1633 ZigList<ZigLLVMDIType **> error_di_types;
16201634};
16211635
16221636enum VarLinkage {
......@@ -1653,6 +1667,7 @@ struct ErrorTableEntry {
16531667 Buf name;
16541668 uint32_t value;
16551669 AstNode *decl_node;
1670 TypeTableEntry *set_with_only_this_in_it;
16561671 // If we generate a constant error name value for this error, we memoize it here.
16571672 // The type of this is array
16581673 ConstExprValue *cached_error_name_val;
......@@ -1920,6 +1935,7 @@ enum IrInstructionId {
19201935 IrInstructionIdArgType,
19211936 IrInstructionIdExport,
19221937 IrInstructionIdErrorReturnTrace,
1938 IrInstructionIdErrorUnion,
19231939};
19241940
19251941struct IrInstruction {
......@@ -1996,7 +2012,6 @@ enum IrUnOp {
19962012 IrUnOpNegation,
19972013 IrUnOpNegationWrap,
19982014 IrUnOpDereference,
1999 IrUnOpError,
20002015 IrUnOpMaybe,
20012016};
20022017
......@@ -2750,6 +2765,13 @@ struct IrInstructionErrorReturnTrace {
27502765 IrInstruction base;
27512766};
27522767
2768struct IrInstructionErrorUnion {
2769 IrInstruction base;
2770
2771 IrInstruction *err_set;
2772 IrInstruction *payload;
2773};
2774
27532775static const size_t slice_ptr_index = 0;
27542776static const size_t slice_len_index = 1;
27552777
src/analyze.cpp+124-88
......@@ -224,7 +224,7 @@ bool type_is_complete(TypeTableEntry *type_entry) {
224224 case TypeTableEntryIdNullLit:
225225 case TypeTableEntryIdMaybe:
226226 case TypeTableEntryIdErrorUnion:
227 case TypeTableEntryIdPureError:
227 case TypeTableEntryIdErrorSet:
228228 case TypeTableEntryIdFn:
229229 case TypeTableEntryIdNamespace:
230230 case TypeTableEntryIdBlock:
......@@ -260,7 +260,7 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
260260 case TypeTableEntryIdNullLit:
261261 case TypeTableEntryIdMaybe:
262262 case TypeTableEntryIdErrorUnion:
263 case TypeTableEntryIdPureError:
263 case TypeTableEntryIdErrorSet:
264264 case TypeTableEntryIdFn:
265265 case TypeTableEntryIdNamespace:
266266 case TypeTableEntryIdBlock:
......@@ -514,29 +514,39 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
514514 }
515515}
516516
517TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
518 if (child_type->error_parent)
519 return child_type->error_parent;
517TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, TypeTableEntry *payload_type) {
518 assert(err_set_type->id == TypeTableEntryIdErrorSet);
519
520 TypeId type_id = {};
521 type_id.id = TypeTableEntryIdErrorUnion;
522 type_id.data.error_union.err_set_type = err_set_type;
523 type_id.data.error_union.payload_type = payload_type;
524
525 auto existing_entry = g->type_table.maybe_get(type_id);
526 if (existing_entry) {
527 return existing_entry->value;
528 }
520529
521530 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorUnion);
522531 entry->is_copyable = true;
523 assert(child_type->type_ref);
524 assert(child_type->di_type);
525 ensure_complete_type(g, child_type);
532 assert(payload_type->type_ref);
533 assert(payload_type->di_type);
534 ensure_complete_type(g, payload_type);
526535
527536 buf_resize(&entry->name, 0);
528 buf_appendf(&entry->name, "%%%s", buf_ptr(&child_type->name));
537 buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name));
529538
530 entry->data.error.child_type = child_type;
539 entry->data.error_union.err_set_type = err_set_type;
540 entry->data.error_union.payload_type = payload_type;
531541
532 if (!type_has_bits(child_type)) {
533 entry->type_ref = g->err_tag_type->type_ref;
534 entry->di_type = g->err_tag_type->di_type;
542 if (!type_has_bits(payload_type)) {
543 entry->type_ref = err_set_type->type_ref;
544 entry->di_type = err_set_type->di_type;
535545
536546 } else {
537547 LLVMTypeRef elem_types[] = {
538 g->err_tag_type->type_ref,
539 child_type->type_ref,
548 err_set_type->type_ref,
549 payload_type->type_ref,
540550 };
541551 entry->type_ref = LLVMStructType(elem_types, 2, false);
542552
......@@ -547,12 +557,12 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
547557 ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name),
548558 compile_unit_scope, di_file, line);
549559
550 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, g->err_tag_type->type_ref);
551 uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, g->err_tag_type->type_ref);
560 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, err_set_type->type_ref);
561 uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, err_set_type->type_ref);
552562 uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, err_union_err_index);
553563
554 uint64_t value_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref);
555 uint64_t value_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, child_type->type_ref);
564 uint64_t value_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, payload_type->type_ref);
565 uint64_t value_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, payload_type->type_ref);
556566 uint64_t value_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref,
557567 err_union_payload_index);
558568
......@@ -565,13 +575,13 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
565575 tag_debug_size_in_bits,
566576 tag_debug_align_in_bits,
567577 tag_offset_in_bits,
568 0, child_type->di_type),
578 0, err_set_type->di_type),
569579 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
570580 "value", di_file, line,
571581 value_debug_size_in_bits,
572582 value_debug_align_in_bits,
573583 value_offset_in_bits,
574 0, child_type->di_type),
584 0, payload_type->di_type),
575585 };
576586
577587 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
......@@ -587,7 +597,7 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
587597 entry->di_type = replacement_di_type;
588598 }
589599
590 child_type->error_parent = entry;
600 g->type_table.put(type_id, entry);
591601 return entry;
592602}
593603
......@@ -937,7 +947,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
937947 handle_is_ptr(fn_type_id->return_type);
938948 bool prefix_arg_error_return_trace = g->have_err_ret_tracing &&
939949 (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
940 fn_type_id->return_type->id == TypeTableEntryIdPureError);
950 fn_type_id->return_type->id == TypeTableEntryIdErrorSet);
941951 // +1 for maybe making the first argument the return value
942952 // +1 for maybe last argument the error return trace
943953 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count);
......@@ -1177,7 +1187,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
11771187 case TypeTableEntryIdUndefLit:
11781188 case TypeTableEntryIdNullLit:
11791189 case TypeTableEntryIdErrorUnion:
1180 case TypeTableEntryIdPureError:
1190 case TypeTableEntryIdErrorSet:
11811191 case TypeTableEntryIdNamespace:
11821192 case TypeTableEntryIdBlock:
11831193 case TypeTableEntryIdBoundFn:
......@@ -1218,7 +1228,7 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
12181228 case TypeTableEntryIdUndefLit:
12191229 case TypeTableEntryIdNullLit:
12201230 case TypeTableEntryIdErrorUnion:
1221 case TypeTableEntryIdPureError:
1231 case TypeTableEntryIdErrorSet:
12221232 case TypeTableEntryIdNamespace:
12231233 case TypeTableEntryIdBlock:
12241234 case TypeTableEntryIdBoundFn:
......@@ -1263,7 +1273,23 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
12631273 zig_unreachable();
12641274}
12651275
1266static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope) {
1276static TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry) {
1277 TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet);
1278 buf_resize(&err_set_type->name, 0);
1279 buf_appendf(&err_set_type->name, "%s.errors", buf_ptr(&fn_entry->symbol_name));
1280 err_set_type->is_copyable = true;
1281 err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref;
1282 err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type;
1283 err_set_type->data.error_set.err_count = 0;
1284 err_set_type->data.error_set.errors = nullptr;
1285 err_set_type->data.error_set.infer_fn = fn_entry;
1286
1287 g->error_di_types.append(&err_set_type->di_type);
1288
1289 return err_set_type;
1290}
1291
1292static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, FnTableEntry *fn_entry) {
12671293 assert(proto_node->type == NodeTypeFnProto);
12681294 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
12691295
......@@ -1359,7 +1385,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13591385 case TypeTableEntryIdStruct:
13601386 case TypeTableEntryIdMaybe:
13611387 case TypeTableEntryIdErrorUnion:
1362 case TypeTableEntryIdPureError:
1388 case TypeTableEntryIdErrorSet:
13631389 case TypeTableEntryIdEnum:
13641390 case TypeTableEntryIdUnion:
13651391 case TypeTableEntryIdFn:
......@@ -1382,8 +1408,13 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13821408 }
13831409 }
13841410
1385 fn_type_id.return_type = (fn_proto->return_type == nullptr) ?
1386 g->builtin_types.entry_void : analyze_type_expr(g, child_scope, fn_proto->return_type);
1411 TypeTableEntry *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type);
1412 if (fn_proto->auto_err_set) {
1413 TypeTableEntry *inferred_err_set_type = get_auto_err_set_type(g, fn_entry);
1414 fn_type_id.return_type = get_error_union_type(g, inferred_err_set_type, specified_return_type);
1415 } else {
1416 fn_type_id.return_type = specified_return_type;
1417 }
13871418
13881419 if (type_is_invalid(fn_type_id.return_type)) {
13891420 return g->builtin_types.entry_invalid;
......@@ -1434,7 +1465,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
14341465 case TypeTableEntryIdStruct:
14351466 case TypeTableEntryIdMaybe:
14361467 case TypeTableEntryIdErrorUnion:
1437 case TypeTableEntryIdPureError:
1468 case TypeTableEntryIdErrorSet:
14381469 case TypeTableEntryIdEnum:
14391470 case TypeTableEntryIdUnion:
14401471 case TypeTableEntryIdFn:
......@@ -2756,7 +2787,8 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) {
27562787 return g->test_fn_type;
27572788
27582789 FnTypeId fn_type_id = {0};
2759 fn_type_id.return_type = get_error_type(g, g->builtin_types.entry_void);
2790 fn_type_id.return_type = get_error_union_type(g, g->builtin_types.entry_global_error_set,
2791 g->builtin_types.entry_void);
27602792 g->test_fn_type = get_fn_type(g, &fn_type_id);
27612793 return g->test_fn_type;
27622794}
......@@ -2824,7 +2856,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
28242856
28252857 Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
28262858
2827 fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope);
2859 fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry);
28282860
28292861 if (fn_proto->section_expr != nullptr) {
28302862 if (fn_table_entry->body_node == nullptr) {
......@@ -2949,29 +2981,6 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope
29492981 g->resolve_queue.append(&tld_fn->base);
29502982}
29512983
2952static void preview_error_value_decl(CodeGen *g, AstNode *node) {
2953 assert(node->type == NodeTypeErrorValueDecl);
2954
2955 ErrorTableEntry *err = allocate<ErrorTableEntry>(1);
2956
2957 err->decl_node = node;
2958 buf_init_from_buf(&err->name, node->data.error_value_decl.name);
2959
2960 auto existing_entry = g->error_table.maybe_get(&err->name);
2961 if (existing_entry) {
2962 // duplicate error definitions allowed and they get the same value
2963 err->value = existing_entry->value->value;
2964 } else {
2965 size_t error_value_count = g->error_decls.length;
2966 assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)g->err_tag_type->data.integral.bit_count));
2967 err->value = (uint32_t)error_value_count;
2968 g->error_decls.append(node);
2969 g->error_table.put(&err->name, err);
2970 }
2971
2972 node->data.error_value_decl.err = err;
2973}
2974
29752984static void preview_comptime_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
29762985 assert(node->type == NodeTypeCompTime);
29772986
......@@ -3045,10 +3054,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
30453054 import->use_decls.append(node);
30463055 break;
30473056 }
3048 case NodeTypeErrorValueDecl:
3049 // error value declarations do not depend on other top level decls
3050 preview_error_value_decl(g, node);
3051 break;
30523057 case NodeTypeTestDecl:
30533058 preview_test_decl(g, node, decls_scope);
30543059 break;
......@@ -3097,6 +3102,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
30973102 case NodeTypeVarLiteral:
30983103 case NodeTypeIfErrorExpr:
30993104 case NodeTypeTestExpr:
3105 case NodeTypeErrorSetDecl:
31003106 zig_unreachable();
31013107 }
31023108}
......@@ -3147,7 +3153,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
31473153 case TypeTableEntryIdStruct:
31483154 case TypeTableEntryIdMaybe:
31493155 case TypeTableEntryIdErrorUnion:
3150 case TypeTableEntryIdPureError:
3156 case TypeTableEntryIdErrorSet:
31513157 case TypeTableEntryIdEnum:
31523158 case TypeTableEntryIdUnion:
31533159 case TypeTableEntryIdFn:
......@@ -3403,13 +3409,16 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
34033409 actual_type->data.maybe.child_type);
34043410 }
34053411
3406 // error
3412 // error union
34073413 if (expected_type->id == TypeTableEntryIdErrorUnion &&
34083414 actual_type->id == TypeTableEntryIdErrorUnion)
34093415 {
34103416 return types_match_const_cast_only(
3411 expected_type->data.error.child_type,
3412 actual_type->data.error.child_type);
3417 expected_type->data.error_union.payload_type,
3418 actual_type->data.error_union.payload_type) &&
3419 types_match_const_cast_only(
3420 expected_type->data.error_union.err_set_type,
3421 actual_type->data.error_union.err_set_type);
34133422 }
34143423
34153424 // fn
......@@ -3625,7 +3634,7 @@ static bool is_container(TypeTableEntry *type_entry) {
36253634 case TypeTableEntryIdNullLit:
36263635 case TypeTableEntryIdMaybe:
36273636 case TypeTableEntryIdErrorUnion:
3628 case TypeTableEntryIdPureError:
3637 case TypeTableEntryIdErrorSet:
36293638 case TypeTableEntryIdFn:
36303639 case TypeTableEntryIdNamespace:
36313640 case TypeTableEntryIdBlock:
......@@ -3673,7 +3682,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
36733682 case TypeTableEntryIdNullLit:
36743683 case TypeTableEntryIdMaybe:
36753684 case TypeTableEntryIdErrorUnion:
3676 case TypeTableEntryIdPureError:
3685 case TypeTableEntryIdErrorSet:
36773686 case TypeTableEntryIdFn:
36783687 case TypeTableEntryIdNamespace:
36793688 case TypeTableEntryIdBlock:
......@@ -3774,14 +3783,36 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ
37743783 &fn_table_entry->analyzed_executable, fn_type_id->return_type, return_type_node);
37753784 fn_table_entry->implicit_return_type = block_return_type;
37763785
3777 if (block_return_type->id == TypeTableEntryIdInvalid ||
3778 fn_table_entry->analyzed_executable.invalid)
3779 {
3786 if (type_is_invalid(block_return_type) || fn_table_entry->analyzed_executable.invalid) {
37803787 assert(g->errors.length > 0);
37813788 fn_table_entry->anal_state = FnAnalStateInvalid;
37823789 return;
37833790 }
37843791
3792 if (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) {
3793 TypeTableEntry *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type;
3794 if (return_err_set_type->data.error_set.infer_fn != nullptr) {
3795 TypeTableEntry *inferred_err_set_type;
3796 if (fn_table_entry->implicit_return_type->id == TypeTableEntryIdErrorSet) {
3797 inferred_err_set_type = fn_table_entry->implicit_return_type;
3798 } else if (fn_table_entry->implicit_return_type->id == TypeTableEntryIdErrorUnion) {
3799 inferred_err_set_type = fn_table_entry->implicit_return_type->data.error_union.err_set_type;
3800 } else {
3801 add_node_error(g, return_type_node,
3802 buf_sprintf("function with inferred error set must return at least one possible error"));
3803 fn_table_entry->anal_state = FnAnalStateInvalid;
3804 return;
3805 }
3806
3807 return_err_set_type->data.error_set.infer_fn = nullptr;
3808 return_err_set_type->data.error_set.err_count = inferred_err_set_type->data.error_set.err_count;
3809 return_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(inferred_err_set_type->data.error_set.err_count);
3810 for (uint32_t i = 0; i < inferred_err_set_type->data.error_set.err_count; i += 1) {
3811 return_err_set_type->data.error_set.errors[i] = inferred_err_set_type->data.error_set.errors[i];
3812 }
3813 }
3814 }
3815
37853816 if (g->verbose_ir) {
37863817 fprintf(stderr, "{ // (analyzed)\n");
37873818 ir_print(g, stderr, &fn_table_entry->analyzed_executable, 4);
......@@ -3791,7 +3822,7 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ
37913822 fn_table_entry->anal_state = FnAnalStateComplete;
37923823}
37933824
3794static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
3825void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
37953826 assert(fn_table_entry->anal_state != FnAnalStateProbing);
37963827 if (fn_table_entry->anal_state != FnAnalStateReady)
37973828 return;
......@@ -4022,7 +4053,8 @@ void semantic_analyze(CodeGen *g) {
40224053 for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) {
40234054 Tld *tld = g->resolve_queue.at(g->resolve_queue_index);
40244055 bool pointer_only = false;
4025 resolve_top_level_decl(g, tld, pointer_only, nullptr);
4056 AstNode *source_node = nullptr;
4057 resolve_top_level_decl(g, tld, pointer_only, source_node);
40264058 }
40274059
40284060 for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
......@@ -4114,7 +4146,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
41144146 case TypeTableEntryIdInt:
41154147 case TypeTableEntryIdFloat:
41164148 case TypeTableEntryIdPointer:
4117 case TypeTableEntryIdPureError:
4149 case TypeTableEntryIdErrorSet:
41184150 case TypeTableEntryIdFn:
41194151 case TypeTableEntryIdEnum:
41204152 return false;
......@@ -4122,7 +4154,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
41224154 case TypeTableEntryIdStruct:
41234155 return type_has_bits(type_entry);
41244156 case TypeTableEntryIdErrorUnion:
4125 return type_has_bits(type_entry->data.error.child_type);
4157 return type_has_bits(type_entry->data.error_union.payload_type);
41264158 case TypeTableEntryIdMaybe:
41274159 return type_has_bits(type_entry->data.maybe.child_type) &&
41284160 type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&
......@@ -4386,9 +4418,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
43864418 case TypeTableEntryIdErrorUnion:
43874419 // TODO better hashing algorithm
43884420 return 3415065496;
4389 case TypeTableEntryIdPureError:
4390 // TODO better hashing algorithm
4391 return 2630160122;
4421 case TypeTableEntryIdErrorSet:
4422 assert(const_val->data.x_err_set != nullptr);
4423 return const_val->data.x_err_set->value ^ 2630160122;
43924424 case TypeTableEntryIdFn:
43934425 return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry);
43944426 case TypeTableEntryIdNamespace:
......@@ -4515,7 +4547,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
45154547 case TypeTableEntryIdMaybe:
45164548 case TypeTableEntryIdErrorUnion:
45174549 case TypeTableEntryIdEnum:
4518 case TypeTableEntryIdPureError:
4550 case TypeTableEntryIdErrorSet:
45194551 case TypeTableEntryIdFn:
45204552 case TypeTableEntryIdBool:
45214553 case TypeTableEntryIdInt:
......@@ -4894,8 +4926,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
48944926 return a->data.x_type == b->data.x_type;
48954927 case TypeTableEntryIdVoid:
48964928 return true;
4897 case TypeTableEntryIdPureError:
4898 return a->data.x_pure_err == b->data.x_pure_err;
4929 case TypeTableEntryIdErrorSet:
4930 return a->data.x_err_set->value == b->data.x_err_set->value;
48994931 case TypeTableEntryIdFn:
49004932 return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry;
49014933 case TypeTableEntryIdBool:
......@@ -5256,9 +5288,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
52565288 buf_appendf(buf, "(union %s constant)", buf_ptr(&type_entry->name));
52575289 return;
52585290 }
5259 case TypeTableEntryIdPureError:
5291 case TypeTableEntryIdErrorSet:
52605292 {
5261 buf_appendf(buf, "(pure error constant)");
5293 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
52625294 return;
52635295 }
52645296 case TypeTableEntryIdArgTuple:
......@@ -5319,8 +5351,7 @@ uint32_t type_id_hash(TypeId x) {
53195351 case TypeTableEntryIdUndefLit:
53205352 case TypeTableEntryIdNullLit:
53215353 case TypeTableEntryIdMaybe:
5322 case TypeTableEntryIdErrorUnion:
5323 case TypeTableEntryIdPureError:
5354 case TypeTableEntryIdErrorSet:
53245355 case TypeTableEntryIdEnum:
53255356 case TypeTableEntryIdUnion:
53265357 case TypeTableEntryIdFn:
......@@ -5329,6 +5360,8 @@ uint32_t type_id_hash(TypeId x) {
53295360 case TypeTableEntryIdBoundFn:
53305361 case TypeTableEntryIdArgTuple:
53315362 zig_unreachable();
5363 case TypeTableEntryIdErrorUnion:
5364 return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
53325365 case TypeTableEntryIdPointer:
53335366 return hash_ptr(x.data.pointer.child_type) +
53345367 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
......@@ -5363,8 +5396,7 @@ bool type_id_eql(TypeId a, TypeId b) {
53635396 case TypeTableEntryIdUndefLit:
53645397 case TypeTableEntryIdNullLit:
53655398 case TypeTableEntryIdMaybe:
5366 case TypeTableEntryIdErrorUnion:
5367 case TypeTableEntryIdPureError:
5399 case TypeTableEntryIdErrorSet:
53685400 case TypeTableEntryIdEnum:
53695401 case TypeTableEntryIdUnion:
53705402 case TypeTableEntryIdFn:
......@@ -5374,6 +5406,10 @@ bool type_id_eql(TypeId a, TypeId b) {
53745406 case TypeTableEntryIdArgTuple:
53755407 case TypeTableEntryIdOpaque:
53765408 zig_unreachable();
5409 case TypeTableEntryIdErrorUnion:
5410 return a.data.error_union.err_set_type == b.data.error_union.err_set_type &&
5411 a.data.error_union.payload_type == b.data.error_union.payload_type;
5412
53775413 case TypeTableEntryIdPointer:
53785414 return a.data.pointer.child_type == b.data.pointer.child_type &&
53795415 a.data.pointer.is_const == b.data.pointer.is_const &&
......@@ -5478,7 +5514,7 @@ static const TypeTableEntryId all_type_ids[] = {
54785514 TypeTableEntryIdNullLit,
54795515 TypeTableEntryIdMaybe,
54805516 TypeTableEntryIdErrorUnion,
5481 TypeTableEntryIdPureError,
5517 TypeTableEntryIdErrorSet,
54825518 TypeTableEntryIdEnum,
54835519 TypeTableEntryIdUnion,
54845520 TypeTableEntryIdFn,
......@@ -5533,7 +5569,7 @@ size_t type_id_index(TypeTableEntryId id) {
55335569 return 13;
55345570 case TypeTableEntryIdErrorUnion:
55355571 return 14;
5536 case TypeTableEntryIdPureError:
5572 case TypeTableEntryIdErrorSet:
55375573 return 15;
55385574 case TypeTableEntryIdEnum:
55395575 return 16;
......@@ -5590,8 +5626,8 @@ const char *type_id_name(TypeTableEntryId id) {
55905626 return "Nullable";
55915627 case TypeTableEntryIdErrorUnion:
55925628 return "ErrorUnion";
5593 case TypeTableEntryIdPureError:
5594 return "Error";
5629 case TypeTableEntryIdErrorSet:
5630 return "ErrorSet";
55955631 case TypeTableEntryIdEnum:
55965632 return "Enum";
55975633 case TypeTableEntryIdUnion:
src/analyze.hpp+2-2
......@@ -30,7 +30,7 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type);
3030TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
3131 AstNode *decl_node, const char *name, ContainerLayout layout);
3232TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
33TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
33TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, TypeTableEntry *payload_type);
3434TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
3535TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
3636TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
......@@ -46,7 +46,6 @@ bool type_has_bits(TypeTableEntry *type_entry);
4646ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
4747
4848
49// TODO move these over, these used to be static
5049bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);
5150VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
5251Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
......@@ -188,6 +187,7 @@ void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, G
188187
189188ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
190189TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g);
190void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);
191191
192192
193193#endif
src/ast_render.cpp+24-5
......@@ -54,6 +54,7 @@ static const char *bin_op_str(BinOpType bin_op) {
5454 case BinOpTypeUnwrapMaybe: return "??";
5555 case BinOpTypeArrayCat: return "++";
5656 case BinOpTypeArrayMult: return "**";
57 case BinOpTypeErrorUnion: return "!";
5758 }
5859 zig_unreachable();
5960}
......@@ -67,7 +68,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
6768 case PrefixOpBinNot: return "~";
6869 case PrefixOpDereference: return "*";
6970 case PrefixOpMaybe: return "?";
70 case PrefixOpError: return "%";
7171 case PrefixOpUnwrapMaybe: return "??";
7272 }
7373 zig_unreachable();
......@@ -174,8 +174,6 @@ static const char *node_type_str(NodeType node_type) {
174174 return "Defer";
175175 case NodeTypeVariableDeclaration:
176176 return "VariableDeclaration";
177 case NodeTypeErrorValueDecl:
178 return "ErrorValueDecl";
179177 case NodeTypeTestDecl:
180178 return "TestDecl";
181179 case NodeTypeIntLiteral:
......@@ -244,6 +242,8 @@ static const char *node_type_str(NodeType node_type) {
244242 return "IfErrorExpr";
245243 case NodeTypeTestExpr:
246244 return "TestExpr";
245 case NodeTypeErrorSetDecl:
246 return "ErrorSetDecl";
247247 }
248248 zig_unreachable();
249249}
......@@ -396,7 +396,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
396396
397397 if (child->type == NodeTypeUse ||
398398 child->type == NodeTypeVariableDeclaration ||
399 child->type == NodeTypeErrorValueDecl ||
400399 child->type == NodeTypeFnProto)
401400 {
402401 fprintf(ar->f, ";");
......@@ -452,6 +451,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
452451 AstNode *return_type_node = node->data.fn_proto.return_type;
453452 assert(return_type_node != nullptr);
454453 fprintf(ar->f, " ");
454 if (node->data.fn_proto.auto_err_set) {
455 fprintf(ar->f, "!");
456 }
455457 render_node_grouped(ar, return_type_node);
456458 break;
457459 }
......@@ -1017,9 +1019,26 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
10171019 render_node_ungrouped(ar, node->data.unwrap_err_expr.op2);
10181020 break;
10191021 }
1022 case NodeTypeErrorSetDecl:
1023 {
1024 fprintf(ar->f, "error {\n");
1025 ar->indent += ar->indent_size;
1026
1027 for (size_t i = 0; i < node->data.err_set_decl.decls.length; i += 1) {
1028 AstNode *field_node = node->data.err_set_decl.decls.at(i);
1029 assert(field_node->type == NodeTypeSymbol);
1030 print_indent(ar);
1031 print_symbol(ar, field_node->data.symbol_expr.symbol);
1032 fprintf(ar->f, ",\n");
1033 }
1034
1035 ar->indent -= ar->indent_size;
1036 print_indent(ar);
1037 fprintf(ar->f, "}");
1038 break;
1039 }
10201040 case NodeTypeFnDecl:
10211041 case NodeTypeParamDecl:
1022 case NodeTypeErrorValueDecl:
10231042 case NodeTypeTestDecl:
10241043 case NodeTypeStructField:
10251044 case NodeTypeUse:
src/codegen.cpp+76-51
......@@ -92,9 +92,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
9292 g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);
9393 buf_resize(&g->global_asm, 0);
9494
95 // reserve index 0 to indicate no error
96 g->error_decls.append(nullptr);
97
9895 if (root_src_path) {
9996 Buf *src_basename = buf_alloc();
10097 Buf *src_dir = buf_alloc();
......@@ -410,7 +407,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e
410407 }
411408 TypeTableEntry *fn_type = fn_table_entry->type_entry;
412409 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
413 if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) {
410 if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdErrorSet) {
414411 return UINT32_MAX;
415412 }
416413 bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type);
......@@ -1442,7 +1439,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
14421439 is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError;
14431440 // TODO: emit a branch to check if the return value is an error
14441441 }
1445 } else if (return_type->id == TypeTableEntryIdPureError) {
1442 } else if (return_type->id == TypeTableEntryIdErrorSet) {
14461443 is_err_return = true;
14471444 }
14481445 if (is_err_return) {
......@@ -1823,7 +1820,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
18231820 } else if (type_entry->id == TypeTableEntryIdEnum) {
18241821 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
18251822 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
1826 } else if (type_entry->id == TypeTableEntryIdPureError ||
1823 } else if (type_entry->id == TypeTableEntryIdErrorSet ||
18271824 type_entry->id == TypeTableEntryIdPointer ||
18281825 type_entry->id == TypeTableEntryIdBool)
18291826 {
......@@ -2139,7 +2136,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable,
21392136
21402137static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) {
21412138 TypeTableEntry *wanted_type = instruction->base.value.type;
2142 assert(wanted_type->id == TypeTableEntryIdPureError);
2139 assert(wanted_type->id == TypeTableEntryIdErrorSet);
21432140
21442141 TypeTableEntry *actual_type = instruction->target->value.type;
21452142 assert(actual_type->id == TypeTableEntryIdInt);
......@@ -2156,11 +2153,11 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I
21562153 eval_min_max_value_int(g, actual_type, &biggest_possible_err_val, true);
21572154
21582155 if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) &&
2159 bigint_as_unsigned(&biggest_possible_err_val) < g->error_decls.length)
2156 bigint_as_unsigned(&biggest_possible_err_val) < g->errors_by_index.length)
21602157 {
21612158 ok_bit = neq_zero_bit;
21622159 } else {
2163 LLVMValueRef error_value_count = LLVMConstInt(actual_type->type_ref, g->error_decls.length, false);
2160 LLVMValueRef error_value_count = LLVMConstInt(actual_type->type_ref, g->errors_by_index.length, false);
21642161 LLVMValueRef in_bounds_bit = LLVMBuildICmp(g->builder, LLVMIntULT, target_val, error_value_count, "");
21652162 ok_bit = LLVMBuildAnd(g->builder, neq_zero_bit, in_bounds_bit, "");
21662163 }
......@@ -2187,15 +2184,15 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, I
21872184 TypeTableEntry *actual_type = instruction->target->value.type;
21882185 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
21892186
2190 if (actual_type->id == TypeTableEntryIdPureError) {
2187 if (actual_type->id == TypeTableEntryIdErrorSet) {
21912188 return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
21922189 g->err_tag_type, wanted_type, target_val);
21932190 } else if (actual_type->id == TypeTableEntryIdErrorUnion) {
2194 if (!type_has_bits(actual_type->data.error.child_type)) {
2191 if (!type_has_bits(actual_type->data.error_union.payload_type)) {
21952192 return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
21962193 g->err_tag_type, wanted_type, target_val);
21972194 } else {
2198 zig_panic("TODO");
2195 zig_panic("TODO err to int when error union payload type not void");
21992196 }
22002197 } else {
22012198 zig_unreachable();
......@@ -2235,7 +2232,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
22352232
22362233 switch (op_id) {
22372234 case IrUnOpInvalid:
2238 case IrUnOpError:
22392235 case IrUnOpMaybe:
22402236 case IrUnOpDereference:
22412237 zig_unreachable();
......@@ -2489,7 +2485,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
24892485 TypeTableEntry *src_return_type = fn_type_id->return_type;
24902486 bool ret_has_bits = type_has_bits(src_return_type);
24912487 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
2492 bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError);
2488 bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet);
24932489 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0);
24942490 bool is_var_args = fn_type_id->is_var_args;
24952491 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
......@@ -2907,7 +2903,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru
29072903static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrInstructionErrName *instruction) {
29082904 assert(g->generate_error_name_table);
29092905
2910 if (g->error_decls.length == 1) {
2906 if (g->errors_by_index.length == 1) {
29112907 LLVMBuildUnreachable(g->builder);
29122908 return nullptr;
29132909 }
......@@ -2915,7 +2911,7 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI
29152911 LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
29162912 if (ir_want_runtime_safety(g, &instruction->base)) {
29172913 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
2918 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false);
2914 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->errors_by_index.length, false);
29192915 add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
29202916 }
29212917
......@@ -3393,11 +3389,11 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
33933389
33943390static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) {
33953391 TypeTableEntry *err_union_type = instruction->value->value.type;
3396 TypeTableEntry *child_type = err_union_type->data.error.child_type;
3392 TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type;
33973393 LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value);
33983394
33993395 LLVMValueRef err_val;
3400 if (type_has_bits(child_type)) {
3396 if (type_has_bits(payload_type)) {
34013397 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
34023398 err_val = gen_load_untyped(g, err_val_ptr, 0, false, "");
34033399 } else {
......@@ -3412,11 +3408,11 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
34123408 TypeTableEntry *ptr_type = instruction->value->value.type;
34133409 assert(ptr_type->id == TypeTableEntryIdPointer);
34143410 TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type;
3415 TypeTableEntry *child_type = err_union_type->data.error.child_type;
3411 TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type;
34163412 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
34173413 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
34183414
3419 if (type_has_bits(child_type)) {
3415 if (type_has_bits(payload_type)) {
34203416 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
34213417 return gen_load_untyped(g, err_val_ptr, 0, false, "");
34223418 } else {
......@@ -3428,13 +3424,13 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
34283424 TypeTableEntry *ptr_type = instruction->value->value.type;
34293425 assert(ptr_type->id == TypeTableEntryIdPointer);
34303426 TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type;
3431 TypeTableEntry *child_type = err_union_type->data.error.child_type;
3427 TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type;
34323428 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
34333429 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
34343430
3435 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->error_decls.length > 1) {
3431 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {
34363432 LLVMValueRef err_val;
3437 if (type_has_bits(child_type)) {
3433 if (type_has_bits(payload_type)) {
34383434 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
34393435 err_val = gen_load_untyped(g, err_val_ptr, 0, false, "");
34403436 } else {
......@@ -3452,7 +3448,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
34523448 LLVMPositionBuilderAtEnd(g->builder, ok_block);
34533449 }
34543450
3455 if (type_has_bits(child_type)) {
3451 if (type_has_bits(payload_type)) {
34563452 return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, "");
34573453 } else {
34583454 return nullptr;
......@@ -3493,10 +3489,10 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable
34933489
34943490 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
34953491
3496 TypeTableEntry *child_type = wanted_type->data.error.child_type;
3492 TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type;
34973493 LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
34983494
3499 if (!type_has_bits(child_type))
3495 if (!type_has_bits(payload_type))
35003496 return err_val;
35013497
35023498 assert(instruction->tmp_ptr);
......@@ -3512,11 +3508,11 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
35123508
35133509 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
35143510
3515 TypeTableEntry *child_type = wanted_type->data.error.child_type;
3511 TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type;
35163512
35173513 LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
35183514
3519 if (!type_has_bits(child_type))
3515 if (!type_has_bits(payload_type))
35203516 return ok_err_val;
35213517
35223518 assert(instruction->tmp_ptr);
......@@ -3527,7 +3523,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
35273523 gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
35283524
35293525 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
3530 gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, child_type, false), payload_val);
3526 gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val);
35313527
35323528 return instruction->tmp_ptr;
35333529}
......@@ -3700,6 +3696,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
37003696 case IrInstructionIdArgType:
37013697 case IrInstructionIdTagType:
37023698 case IrInstructionIdExport:
3699 case IrInstructionIdErrorUnion:
37033700 zig_unreachable();
37043701 case IrInstructionIdReturn:
37053702 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
......@@ -3933,7 +3930,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
39333930 case TypeTableEntryIdUndefLit:
39343931 case TypeTableEntryIdNullLit:
39353932 case TypeTableEntryIdErrorUnion:
3936 case TypeTableEntryIdPureError:
3933 case TypeTableEntryIdErrorSet:
39373934 case TypeTableEntryIdNamespace:
39383935 case TypeTableEntryIdBlock:
39393936 case TypeTableEntryIdBoundFn:
......@@ -4026,10 +4023,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
40264023 switch (type_entry->id) {
40274024 case TypeTableEntryIdInt:
40284025 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
4029 case TypeTableEntryIdPureError:
4030 assert(const_val->data.x_pure_err);
4031 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,
4032 const_val->data.x_pure_err->value, false);
4026 case TypeTableEntryIdErrorSet:
4027 assert(const_val->data.x_err_set != nullptr);
4028 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
4029 const_val->data.x_err_set->value, false);
40334030 case TypeTableEntryIdFloat:
40344031 switch (type_entry->data.floating.bit_count) {
40354032 case 32:
......@@ -4330,8 +4327,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
43304327 }
43314328 case TypeTableEntryIdErrorUnion:
43324329 {
4333 TypeTableEntry *child_type = type_entry->data.error.child_type;
4334 if (!type_has_bits(child_type)) {
4330 TypeTableEntry *payload_type = type_entry->data.error_union.payload_type;
4331 if (!type_has_bits(payload_type)) {
43354332 uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;
43364333 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
43374334 } else {
......@@ -4340,7 +4337,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
43404337 bool make_unnamed_struct;
43414338 if (const_val->data.x_err_union.err) {
43424339 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
4343 err_payload_value = LLVMConstNull(child_type->type_ref);
4340 err_payload_value = LLVMConstNull(payload_type->type_ref);
43444341 make_unnamed_struct = false;
43454342 } else {
43464343 err_tag_value = LLVMConstNull(g->err_tag_type->type_ref);
......@@ -4410,21 +4407,20 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const
44104407}
44114408
44124409static void generate_error_name_table(CodeGen *g) {
4413 if (g->err_name_table != nullptr || !g->generate_error_name_table || g->error_decls.length == 1) {
4410 if (g->err_name_table != nullptr || !g->generate_error_name_table || g->errors_by_index.length == 1) {
44144411 return;
44154412 }
44164413
4417 assert(g->error_decls.length > 0);
4414 assert(g->errors_by_index.length > 0);
44184415
44194416 TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
44204417 TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type);
44214418
4422 LLVMValueRef *values = allocate<LLVMValueRef>(g->error_decls.length);
4419 LLVMValueRef *values = allocate<LLVMValueRef>(g->errors_by_index.length);
44234420 values[0] = LLVMGetUndef(str_type->type_ref);
4424 for (size_t i = 1; i < g->error_decls.length; i += 1) {
4425 AstNode *error_decl_node = g->error_decls.at(i);
4426 assert(error_decl_node->type == NodeTypeErrorValueDecl);
4427 Buf *name = error_decl_node->data.error_value_decl.name;
4421 for (size_t i = 1; i < g->errors_by_index.length; i += 1) {
4422 ErrorTableEntry *err_entry = g->errors_by_index.at(i);
4423 Buf *name = &err_entry->name;
44284424
44294425 g->largest_err_name_len = max(g->largest_err_name_len, buf_len(name));
44304426
......@@ -4443,7 +4439,7 @@ static void generate_error_name_table(CodeGen *g) {
44434439 values[i] = LLVMConstNamedStruct(str_type->type_ref, fields, 2);
44444440 }
44454441
4446 LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, (unsigned)g->error_decls.length);
4442 LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, (unsigned)g->errors_by_index.length);
44474443
44484444 g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init),
44494445 buf_ptr(get_mangled_name(g, buf_create_from_str("__zig_err_name_table"), false)));
......@@ -4573,6 +4569,28 @@ static void validate_inline_fns(CodeGen *g) {
45734569static void do_code_gen(CodeGen *g) {
45744570 assert(!g->errors.length);
45754571
4572 {
4573 // create debug type for error sets
4574 assert(g->err_enumerators.length == g->errors_by_index.length);
4575 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, g->err_tag_type->type_ref);
4576 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, g->err_tag_type->type_ref);
4577 ZigLLVMDIFile *err_set_di_file = nullptr;
4578 ZigLLVMDIType *err_set_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
4579 ZigLLVMCompileUnitToScope(g->compile_unit), buf_ptr(&g->builtin_types.entry_global_error_set->name),
4580 err_set_di_file, 0,
4581 tag_debug_size_in_bits,
4582 tag_debug_align_in_bits,
4583 g->err_enumerators.items, g->err_enumerators.length,
4584 g->err_tag_type->di_type, "");
4585 ZigLLVMReplaceTemporary(g->dbuilder, g->builtin_types.entry_global_error_set->di_type, err_set_di_type);
4586 g->builtin_types.entry_global_error_set->di_type = err_set_di_type;
4587
4588 for (size_t i = 0; i < g->error_di_types.length; i += 1) {
4589 ZigLLVMDIType **di_type_ptr = g->error_di_types.at(i);
4590 *di_type_ptr = err_set_di_type;
4591 }
4592 }
4593
45764594 codegen_add_time_event(g, "Code Generation");
45774595
45784596 generate_error_name_table(g);
......@@ -5176,16 +5194,23 @@ static void define_builtin_types(CodeGen *g) {
51765194 }
51775195
51785196 {
5179 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
5197 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorSet);
51805198 buf_init_from_str(&entry->name, "error");
51815199
51825200 // TODO allow overriding this type and keep track of max value and emit an
51835201 // error if there are too many errors declared
51845202 g->err_tag_type = g->builtin_types.entry_u16;
51855203
5186 g->builtin_types.entry_pure_error = entry;
5204 g->builtin_types.entry_global_error_set = entry;
51875205 entry->type_ref = g->err_tag_type->type_ref;
5188 entry->di_type = g->err_tag_type->di_type;
5206
5207 entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
5208 ZigLLVMTag_DW_enumeration_type(), "error",
5209 ZigLLVMCompileUnitToScope(g->compile_unit), nullptr, 0);
5210
5211 // reserve index 0 to indicate no error
5212 g->err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, "(none)", 0));
5213 g->errors_by_index.append(nullptr);
51895214
51905215 g->primitive_type_table.put(&entry->name, entry);
51915216 }
......@@ -5815,7 +5840,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry
58155840 case TypeTableEntryIdBoundFn:
58165841 case TypeTableEntryIdArgTuple:
58175842 case TypeTableEntryIdErrorUnion:
5818 case TypeTableEntryIdPureError:
5843 case TypeTableEntryIdErrorSet:
58195844 zig_unreachable();
58205845 case TypeTableEntryIdVoid:
58215846 case TypeTableEntryIdUnreachable:
......@@ -5988,7 +6013,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
59886013 return;
59896014 }
59906015 case TypeTableEntryIdErrorUnion:
5991 case TypeTableEntryIdPureError:
6016 case TypeTableEntryIdErrorSet:
59926017 case TypeTableEntryIdFn:
59936018 zig_panic("TODO implement get_c_type for more types");
59946019 case TypeTableEntryIdInvalid:
......@@ -6155,7 +6180,7 @@ static void gen_h_file(CodeGen *g) {
61556180 case TypeTableEntryIdUndefLit:
61566181 case TypeTableEntryIdNullLit:
61576182 case TypeTableEntryIdErrorUnion:
6158 case TypeTableEntryIdPureError:
6183 case TypeTableEntryIdErrorSet:
61596184 case TypeTableEntryIdNamespace:
61606185 case TypeTableEntryIdBlock:
61616186 case TypeTableEntryIdBoundFn:
src/ir.cpp+533-163
......@@ -580,6 +580,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorReturnTrace
580580 return IrInstructionIdErrorReturnTrace;
581581}
582582
583static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) {
584 return IrInstructionIdErrorUnion;
585}
586
583587template<typename T>
584588static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
585589 T *special_instruction = allocate<T>(1);
......@@ -2326,6 +2330,19 @@ static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope,
23262330 return &instruction->base;
23272331}
23282332
2333static IrInstruction *ir_build_error_union(IrBuilder *irb, Scope *scope, AstNode *source_node,
2334 IrInstruction *err_set, IrInstruction *payload)
2335{
2336 IrInstructionErrorUnion *instruction = ir_build_instruction<IrInstructionErrorUnion>(irb, scope, source_node);
2337 instruction->err_set = err_set;
2338 instruction->payload = payload;
2339
2340 ir_ref_instruction(err_set, irb->current_basic_block);
2341 ir_ref_instruction(payload, irb->current_basic_block);
2342
2343 return &instruction->base;
2344}
2345
23292346static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
23302347 results[ReturnKindUnconditional] = 0;
23312348 results[ReturnKindError] = 0;
......@@ -2800,6 +2817,23 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
28002817 return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
28012818}
28022819
2820static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
2821 assert(node->type == NodeTypeBinOpExpr);
2822
2823 AstNode *op1_node = node->data.bin_op_expr.op1;
2824 AstNode *op2_node = node->data.bin_op_expr.op2;
2825
2826 IrInstruction *err_set = ir_gen_node(irb, op1_node, parent_scope);
2827 if (err_set == irb->codegen->invalid_instruction)
2828 return irb->codegen->invalid_instruction;
2829
2830 IrInstruction *payload = ir_gen_node(irb, op2_node, parent_scope);
2831 if (payload == irb->codegen->invalid_instruction)
2832 return irb->codegen->invalid_instruction;
2833
2834 return ir_build_error_union(irb, parent_scope, node, err_set, payload);
2835}
2836
28032837static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) {
28042838 assert(node->type == NodeTypeBinOpExpr);
28052839
......@@ -2887,6 +2921,8 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
28872921 return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult);
28882922 case BinOpTypeUnwrapMaybe:
28892923 return ir_gen_maybe_ok_or(irb, scope, node);
2924 case BinOpTypeErrorUnion:
2925 return ir_gen_error_union(irb, scope, node);
28902926 }
28912927 zig_unreachable();
28922928}
......@@ -3990,8 +4026,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
39904026 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
39914027 case PrefixOpMaybe:
39924028 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval);
3993 case PrefixOpError:
3994 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpError), lval);
39954029 case PrefixOpUnwrapMaybe:
39964030 return ir_gen_maybe_assert_ok(irb, scope, node, lval);
39974031 }
......@@ -5165,7 +5199,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast
51655199
51665200static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) {
51675201 assert(node->type == NodeTypeErrorType);
5168 return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_pure_error);
5202 return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_global_error_set);
51695203}
51705204
51715205static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
......@@ -5249,8 +5283,6 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
52495283 Scope *err_scope;
52505284 if (var_node) {
52515285 assert(var_node->type == NodeTypeSymbol);
5252 IrInstruction *var_type = ir_build_const_type(irb, parent_scope, node,
5253 irb->codegen->builtin_types.entry_pure_error);
52545286 Buf *var_name = var_node->data.symbol_expr.symbol;
52555287 bool is_const = true;
52565288 bool is_shadowable = false;
......@@ -5258,7 +5290,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
52585290 is_const, is_const, is_shadowable, is_comptime);
52595291 err_scope = var->child_scope;
52605292 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
5261 ir_build_var_decl(irb, err_scope, var_node, var, var_type, nullptr, err_val);
5293 ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
52625294 } else {
52635295 err_scope = parent_scope;
52645296 }
......@@ -5348,6 +5380,70 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope,
53485380 return ir_build_const_type(irb, parent_scope, node, container_type);
53495381}
53505382
5383static TypeTableEntry *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstNode *node,
5384 ErrorTableEntry *err_entry)
5385{
5386 TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet);
5387 buf_resize(&err_set_type->name, 0);
5388 buf_appendf(&err_set_type->name, "@typeOf(error.%s)", buf_ptr(&err_entry->name));
5389 err_set_type->is_copyable = true;
5390 err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref;
5391 err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type;
5392 err_set_type->data.error_set.err_count = 1;
5393 err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1);
5394
5395 g->error_di_types.append(&err_set_type->di_type);
5396
5397 err_set_type->data.error_set.errors[0] = err_entry;
5398
5399 return err_set_type;
5400}
5401
5402static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
5403 assert(node->type == NodeTypeErrorSetDecl);
5404
5405 uint32_t err_count = node->data.err_set_decl.decls.length;
5406
5407 if (err_count == 0) {
5408 add_node_error(irb->codegen, node, buf_sprintf("empty error set"));
5409 return irb->codegen->invalid_instruction;
5410 }
5411
5412 Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error set", node);
5413 TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet);
5414 buf_init_from_buf(&err_set_type->name, type_name);
5415 err_set_type->is_copyable = true;
5416 err_set_type->type_ref = irb->codegen->builtin_types.entry_global_error_set->type_ref;
5417 err_set_type->di_type = irb->codegen->builtin_types.entry_global_error_set->di_type;
5418 err_set_type->data.error_set.err_count = err_count;
5419 err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(err_count);
5420
5421 irb->codegen->error_di_types.append(&err_set_type->di_type);
5422
5423 for (uint32_t i = 0; i < err_count; i += 1) {
5424 AstNode *symbol_node = node->data.err_set_decl.decls.at(i);
5425 assert(symbol_node->type == NodeTypeSymbol);
5426 Buf *err_name = symbol_node->data.symbol_expr.symbol;
5427 ErrorTableEntry *err = allocate<ErrorTableEntry>(1);
5428 err->decl_node = symbol_node;
5429 buf_init_from_buf(&err->name, err_name);
5430
5431 auto existing_entry = irb->codegen->error_table.put_unique(err_name, err);
5432 if (existing_entry) {
5433 err->value = existing_entry->value->value;
5434 } else {
5435 size_t error_value_count = irb->codegen->errors_by_index.length;
5436 assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)irb->codegen->err_tag_type->data.integral.bit_count));
5437 err->value = error_value_count;
5438 irb->codegen->errors_by_index.append(err);
5439 irb->codegen->err_enumerators.append(ZigLLVMCreateDebugEnumerator(irb->codegen->dbuilder,
5440 buf_ptr(err_name), error_value_count));
5441 }
5442 err_set_type->data.error_set.errors[i] = err;
5443 }
5444 return ir_build_const_type(irb, parent_scope, node, err_set_type);
5445}
5446
53515447static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
53525448 assert(node->type == NodeTypeFnProto);
53535449
......@@ -5401,7 +5497,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
54015497 case NodeTypeStructField:
54025498 case NodeTypeFnDef:
54035499 case NodeTypeFnDecl:
5404 case NodeTypeErrorValueDecl:
54055500 case NodeTypeTestDecl:
54065501 zig_unreachable();
54075502 case NodeTypeBlock:
......@@ -5482,6 +5577,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
54825577 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
54835578 case NodeTypeFnProto:
54845579 return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval);
5580 case NodeTypeErrorSetDecl:
5581 return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval);
54855582 }
54865583 zig_unreachable();
54875584}
......@@ -6301,25 +6398,32 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
63016398 return ImplicitCastMatchResultYes;
63026399 }
63036400
6304 // implicit T to %T
6401 // implicit T to U!T
63056402 if (expected_type->id == TypeTableEntryIdErrorUnion &&
6306 ir_types_match_with_implicit_cast(ira, expected_type->data.error.child_type, actual_type, value))
6403 ir_types_match_with_implicit_cast(ira, expected_type->data.error_union.payload_type, actual_type, value))
63076404 {
63086405 return ImplicitCastMatchResultYes;
63096406 }
63106407
6311 // implicit conversion from pure error to error union type
6408 // implicit conversion from error set to error union type
63126409 if (expected_type->id == TypeTableEntryIdErrorUnion &&
6313 actual_type->id == TypeTableEntryIdPureError)
6410 actual_type->id == TypeTableEntryIdErrorSet)
6411 {
6412 return ImplicitCastMatchResultYes;
6413 }
6414
6415 // implicit conversion from error set to another error set
6416 if (expected_type->id == TypeTableEntryIdErrorSet &&
6417 actual_type->id == TypeTableEntryIdErrorSet)
63146418 {
63156419 return ImplicitCastMatchResultYes;
63166420 }
63176421
6318 // implicit conversion from T to %?T
6422 // implicit conversion from T to U!?T
63196423 if (expected_type->id == TypeTableEntryIdErrorUnion &&
6320 expected_type->data.error.child_type->id == TypeTableEntryIdMaybe &&
6424 expected_type->data.error_union.payload_type->id == TypeTableEntryIdMaybe &&
63216425 ir_types_match_with_implicit_cast(ira,
6322 expected_type->data.error.child_type->data.maybe.child_type,
6426 expected_type->data.error_union.payload_type->data.maybe.child_type,
63236427 actual_type, value))
63246428 {
63256429 return ImplicitCastMatchResultYes;
......@@ -6503,7 +6607,19 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
65036607 if (type_is_invalid(prev_inst->value.type)) {
65046608 return ira->codegen->builtin_types.entry_invalid;
65056609 }
6506 bool any_are_pure_error = (prev_inst->value.type->id == TypeTableEntryIdPureError);
6610 ErrorTableEntry **errors = nullptr;
6611 TypeTableEntry *err_set_type = nullptr;
6612 if (prev_inst->value.type == ira->codegen->builtin_types.entry_global_error_set) {
6613 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
6614 } else if (prev_inst->value.type->id == TypeTableEntryIdErrorSet) {
6615 err_set_type = prev_inst->value.type;
6616 errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
6617 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
6618 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
6619 errors[error_entry->value] = error_entry;
6620 }
6621 }
6622
65076623 bool any_are_null = (prev_inst->value.type->id == TypeTableEntryIdNullLit);
65086624 bool convert_to_const_slice = false;
65096625 for (size_t i = 1; i < instruction_count; i += 1) {
......@@ -6524,27 +6640,133 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
65246640 continue;
65256641 }
65266642
6527 if (prev_type->id == TypeTableEntryIdPureError) {
6643 if (prev_type->id == TypeTableEntryIdNullLit) {
65286644 prev_inst = cur_inst;
65296645 continue;
65306646 }
65316647
6532 if (prev_type->id == TypeTableEntryIdNullLit) {
6533 prev_inst = cur_inst;
6648 if (cur_type->id == TypeTableEntryIdNullLit) {
6649 any_are_null = true;
65346650 continue;
65356651 }
65366652
6537 if (cur_type->id == TypeTableEntryIdPureError) {
6538 if (prev_type->id == TypeTableEntryIdArray) {
6539 convert_to_const_slice = true;
6653 if (prev_type->id == TypeTableEntryIdErrorSet) {
6654 assert(err_set_type != nullptr);
6655 if (cur_type->id == TypeTableEntryIdErrorSet) {
6656 if (err_set_type == ira->codegen->builtin_types.entry_global_error_set) {
6657 continue;
6658 }
6659 if (cur_type == ira->codegen->builtin_types.entry_global_error_set) {
6660 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
6661 prev_inst = cur_inst;
6662 continue;
6663 }
6664 // if err_set_type is a superset of cur_type, keep err_set_type.
6665 // if cur_type is a superset of err_set_type, switch err_set_type to cur_type
6666 // otherwise emit a compile error
6667 bool prev_is_superset = true;
6668 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
6669 ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];
6670 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
6671 if (error_entry == nullptr) {
6672 prev_is_superset = false;
6673 break;
6674 }
6675 }
6676 if (prev_is_superset) {
6677 continue;
6678 }
6679
6680 // unset everything in errors
6681 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
6682 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
6683 errors[error_entry->value] = nullptr;
6684 }
6685 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
6686 ErrorTableEntry *error_entry = cur_type->data.error_set.errors[i];
6687 errors[error_entry->value] = error_entry;
6688 }
6689 bool cur_is_superset = true;
6690 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
6691 ErrorTableEntry *contained_error_entry = err_set_type->data.error_set.errors[i];
6692 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
6693 if (error_entry == nullptr) {
6694 cur_is_superset = false;
6695 break;
6696 }
6697 }
6698 if (cur_is_superset) {
6699 err_set_type = cur_inst->value.type;
6700 prev_inst = cur_inst;
6701 continue;
6702 }
6703 } else if (cur_type->id == TypeTableEntryIdErrorUnion) {
6704 // err_set_type must be a subset of cur_type's error set
6705 // unset everything in errors
6706 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
6707 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
6708 errors[error_entry->value] = nullptr;
6709 }
6710 TypeTableEntry *cur_err_set_type = cur_type->data.error_union.err_set_type;
6711 for (uint32_t i = 0; i < cur_err_set_type->data.error_set.err_count; i += 1) {
6712 ErrorTableEntry *error_entry = cur_err_set_type->data.error_set.errors[i];
6713 errors[error_entry->value] = error_entry;
6714 }
6715 bool cur_is_superset = true;
6716 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
6717 ErrorTableEntry *contained_error_entry = err_set_type->data.error_set.errors[i];
6718 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
6719 if (error_entry == nullptr) {
6720 cur_is_superset = false;
6721 break;
6722 }
6723 }
6724 if (cur_is_superset) {
6725 err_set_type = cur_err_set_type;
6726 prev_inst = cur_inst;
6727 continue;
6728 }
6729 } else {
6730 prev_inst = cur_inst;
6731 continue;
65406732 }
6541 any_are_pure_error = true;
6542 continue;
65436733 }
65446734
6545 if (cur_type->id == TypeTableEntryIdNullLit) {
6546 any_are_null = true;
6547 continue;
6735 if (cur_type->id == TypeTableEntryIdErrorSet) {
6736 if (prev_type->id == TypeTableEntryIdArray) {
6737 convert_to_const_slice = true;
6738 }
6739 if (cur_type == ira->codegen->builtin_types.entry_global_error_set) {
6740 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
6741 continue;
6742 }
6743 if (err_set_type == ira->codegen->builtin_types.entry_global_error_set) {
6744 continue;
6745 }
6746 if (err_set_type == nullptr) {
6747 err_set_type = cur_type;
6748 errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
6749 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
6750 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
6751 errors[error_entry->value] = error_entry;
6752 }
6753 continue;
6754 }
6755 if (prev_type->id == TypeTableEntryIdErrorUnion) {
6756 // the cur type error set must be a subset
6757 bool prev_is_superset = true;
6758 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
6759 ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];
6760 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
6761 if (error_entry == nullptr) {
6762 prev_is_superset = false;
6763 break;
6764 }
6765 }
6766 if (prev_is_superset) {
6767 continue;
6768 }
6769 }
65486770 }
65496771
65506772 if (types_match_const_cast_only(prev_type, cur_type)) {
......@@ -6574,20 +6796,20 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
65746796 }
65756797
65766798 if (prev_type->id == TypeTableEntryIdErrorUnion &&
6577 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
6799 types_match_const_cast_only(prev_type->data.error_union.payload_type, cur_type))
65786800 {
65796801 continue;
65806802 }
65816803
65826804 if (cur_type->id == TypeTableEntryIdErrorUnion &&
6583 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
6805 types_match_const_cast_only(cur_type->data.error_union.payload_type, prev_type))
65846806 {
65856807 prev_inst = cur_inst;
65866808 continue;
65876809 }
65886810
65896811 if (prev_type->id == TypeTableEntryIdMaybe &&
6590 types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type))
6812 types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type))
65916813 {
65926814 continue;
65936815 }
......@@ -6700,16 +6922,19 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
67006922
67016923 return ira->codegen->builtin_types.entry_invalid;
67026924 }
6925
6926 free(errors);
6927
67036928 if (convert_to_const_slice) {
67046929 assert(prev_inst->value.type->id == TypeTableEntryIdArray);
67056930 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, prev_inst->value.type->data.array.child_type, true);
67066931 TypeTableEntry *slice_type = get_slice_type(ira->codegen, ptr_type);
6707 if (any_are_pure_error) {
6708 return get_error_type(ira->codegen, slice_type);
6932 if (err_set_type != nullptr) {
6933 return get_error_union_type(ira->codegen, err_set_type, slice_type);
67096934 } else {
67106935 return slice_type;
67116936 }
6712 } else if (any_are_pure_error && prev_inst->value.type->id != TypeTableEntryIdPureError) {
6937 } else if (err_set_type != nullptr && prev_inst->value.type->id != TypeTableEntryIdErrorSet) {
67136938 if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt ||
67146939 prev_inst->value.type->id == TypeTableEntryIdNumLitFloat)
67156940 {
......@@ -6723,7 +6948,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
67236948 } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) {
67246949 return prev_inst->value.type;
67256950 } else {
6726 return get_error_type(ira->codegen, prev_inst->value.type);
6951 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type);
67276952 }
67286953 } else if (any_are_null && prev_inst->value.type->id != TypeTableEntryIdNullLit) {
67296954 if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt ||
......@@ -7199,7 +7424,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
71997424 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
72007425
72017426 if (instr_is_comptime(value)) {
7202 TypeTableEntry *payload_type = wanted_type->data.error.child_type;
7427 TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type;
72037428 IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type);
72047429 if (type_is_invalid(casted_payload->value.type))
72057430 return ira->codegen->invalid_instruction;
......@@ -7224,8 +7449,43 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
72247449 return result;
72257450}
72267451
7227static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
7228 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
7452static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
7453 TypeTableEntry *wanted_type)
7454{
7455 TypeTableEntry *contained_set = value->value.type;
7456 TypeTableEntry *container_set = wanted_type;
7457
7458 assert(contained_set->id == TypeTableEntryIdErrorSet);
7459 assert(container_set->id == TypeTableEntryIdErrorSet);
7460
7461 if (container_set->data.error_set.infer_fn == nullptr &&
7462 container_set != ira->codegen->builtin_types.entry_global_error_set)
7463 {
7464 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
7465 for (uint32_t i = 0; i < container_set->data.error_set.err_count; i += 1) {
7466 ErrorTableEntry *error_entry = container_set->data.error_set.errors[i];
7467 errors[error_entry->value] = error_entry;
7468 }
7469 ErrorMsg *err_msg = nullptr;
7470 for (uint32_t i = 0; i < contained_set->data.error_set.err_count; i += 1) {
7471 ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];
7472 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
7473 if (error_entry == nullptr) {
7474 if (err_msg == nullptr) {
7475 err_msg = ir_add_error(ira, source_instr,
7476 buf_sprintf("invalid cast of error set '%s' to error set '%s'",
7477 buf_ptr(&contained_set->name), buf_ptr(&container_set->name)));
7478 }
7479 add_error_note(ira->codegen, err_msg, contained_error_entry->decl_node,
7480 buf_sprintf("'%s.%s' not present in '%s'", buf_ptr(&contained_set->name),
7481 buf_ptr(&contained_error_entry->name), buf_ptr(&container_set->name)));
7482 }
7483 }
7484 free(errors);
7485 if (err_msg != nullptr) {
7486 return ira->codegen->invalid_instruction;
7487 }
7488 }
72297489
72307490 if (instr_is_comptime(value)) {
72317491 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
......@@ -7236,7 +7496,30 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
72367496 source_instr->scope, source_instr->source_node);
72377497 const_instruction->base.value.type = wanted_type;
72387498 const_instruction->base.value.special = ConstValSpecialStatic;
7239 const_instruction->base.value.data.x_err_union.err = val->data.x_pure_err;
7499 const_instruction->base.value.data.x_err_set = val->data.x_err_set;
7500 return &const_instruction->base;
7501 }
7502
7503 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, CastOpNoop);
7504 result->value.type = wanted_type;
7505 return result;
7506}
7507
7508static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
7509 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
7510
7511 IrInstruction *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type);
7512
7513 if (instr_is_comptime(casted_value)) {
7514 ConstExprValue *val = ir_resolve_const(ira, casted_value, UndefBad);
7515 if (!val)
7516 return ira->codegen->invalid_instruction;
7517
7518 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
7519 source_instr->scope, source_instr->source_node);
7520 const_instruction->base.value.type = wanted_type;
7521 const_instruction->base.value.special = ConstValSpecialStatic;
7522 const_instruction->base.value.data.x_err_union.err = val->data.x_err_set;
72407523 const_instruction->base.value.data.x_err_union.payload = nullptr;
72417524 return &const_instruction->base;
72427525 }
......@@ -7616,9 +7899,12 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
76167899 return result;
76177900}
76187901
7619static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target) {
7902static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
7903 TypeTableEntry *wanted_type)
7904{
76207905 assert(target->value.type->id == TypeTableEntryIdInt);
76217906 assert(!target->value.type->data.integral.is_signed);
7907 assert(wanted_type->id == TypeTableEntryIdErrorSet);
76227908
76237909 if (instr_is_comptime(target)) {
76247910 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
......@@ -7626,10 +7912,10 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
76267912 return ira->codegen->invalid_instruction;
76277913
76287914 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
7629 source_instr->source_node, ira->codegen->builtin_types.entry_pure_error);
7915 source_instr->source_node, wanted_type);
76307916
76317917 BigInt err_count;
7632 bigint_init_unsigned(&err_count, ira->codegen->error_decls.length);
7918 bigint_init_unsigned(&err_count, ira->codegen->errors_by_index.length);
76337919 if (bigint_cmp_zero(&val->data.x_bigint) == CmpEQ || bigint_cmp(&val->data.x_bigint, &err_count) != CmpLT) {
76347920 Buf *val_buf = buf_alloc();
76357921 bigint_append_buf(val_buf, &val->data.x_bigint, 10);
......@@ -7639,13 +7925,12 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
76397925 }
76407926
76417927 size_t index = bigint_as_unsigned(&val->data.x_bigint);
7642 AstNode *error_decl_node = ira->codegen->error_decls.at(index);
7643 result->value.data.x_pure_err = error_decl_node->data.error_value_decl.err;
7928 result->value.data.x_err_set = ira->codegen->errors_by_index.at(index);
76447929 return result;
76457930 }
76467931
76477932 IrInstruction *result = ir_build_int_to_err(&ira->new_irb, source_instr->scope, source_instr->source_node, target);
7648 result->value.type = ira->codegen->builtin_types.entry_pure_error;
7933 result->value.type = wanted_type;
76497934 return result;
76507935}
76517936
......@@ -7667,8 +7952,8 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
76677952 ErrorTableEntry *err;
76687953 if (err_type->id == TypeTableEntryIdErrorUnion) {
76697954 err = val->data.x_err_union.err;
7670 } else if (err_type->id == TypeTableEntryIdPureError) {
7671 err = val->data.x_pure_err;
7955 } else if (err_type->id == TypeTableEntryIdErrorSet) {
7956 err = val->data.x_err_set;
76727957 } else {
76737958 zig_unreachable();
76747959 }
......@@ -7689,7 +7974,7 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
76897974 }
76907975
76917976 BigInt bn;
7692 bigint_init_unsigned(&bn, ira->codegen->error_decls.length);
7977 bigint_init_unsigned(&bn, ira->codegen->errors_by_index.length);
76937978 if (!bigint_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) {
76947979 ir_add_error_node(ira, source_instr->source_node,
76957980 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
......@@ -7734,6 +8019,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
77348019 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
77358020 }
77368021
8022 // explicit error set cast
8023 if (wanted_type->id == TypeTableEntryIdErrorSet &&
8024 actual_type->id == TypeTableEntryIdErrorSet)
8025 {
8026 return ir_analyze_err_set_cast(ira, source_instr, value, wanted_type);
8027 }
8028
77378029 // explicit cast from int to float
77388030 if (wanted_type->id == TypeTableEntryIdFloat &&
77398031 actual_type->id == TypeTableEntryIdInt)
......@@ -7894,12 +8186,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
78948186
78958187 // explicit cast from child type of error type to error type
78968188 if (wanted_type->id == TypeTableEntryIdErrorUnion) {
7897 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
8189 if (types_match_const_cast_only(wanted_type->data.error_union.payload_type, actual_type)) {
78988190 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
78998191 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
79008192 actual_type->id == TypeTableEntryIdNumLitFloat)
79018193 {
7902 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type, true)) {
8194 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
79038195 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
79048196 } else {
79058197 return ira->codegen->invalid_instruction;
......@@ -7909,16 +8201,16 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
79098201
79108202 // explicit cast from [N]T to %[]const T
79118203 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
7912 is_slice(wanted_type->data.error.child_type) &&
8204 is_slice(wanted_type->data.error_union.payload_type) &&
79138205 actual_type->id == TypeTableEntryIdArray)
79148206 {
79158207 TypeTableEntry *ptr_type =
7916 wanted_type->data.error.child_type->data.structure.fields[slice_ptr_index].type_entry;
8208 wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index].type_entry;
79178209 assert(ptr_type->id == TypeTableEntryIdPointer);
79188210 if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
79198211 types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
79208212 {
7921 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error.child_type, value);
8213 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
79228214 if (type_is_invalid(cast1->value.type))
79238215 return ira->codegen->invalid_instruction;
79248216
......@@ -7930,25 +8222,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
79308222 }
79318223 }
79328224
7933 // explicit cast from pure error to error union type
8225 // explicit cast from error set to error union type
79348226 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
7935 actual_type->id == TypeTableEntryIdPureError)
8227 actual_type->id == TypeTableEntryIdErrorSet)
79368228 {
79378229 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
79388230 }
79398231
79408232 // explicit cast from T to %?T
79418233 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
7942 wanted_type->data.error.child_type->id == TypeTableEntryIdMaybe &&
8234 wanted_type->data.error_union.payload_type->id == TypeTableEntryIdMaybe &&
79438235 actual_type->id != TypeTableEntryIdMaybe)
79448236 {
7945 TypeTableEntry *wanted_child_type = wanted_type->data.error.child_type->data.maybe.child_type;
8237 TypeTableEntry *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
79468238 if (types_match_const_cast_only(wanted_child_type, actual_type) ||
79478239 actual_type->id == TypeTableEntryIdNullLit ||
79488240 actual_type->id == TypeTableEntryIdNumLitInt ||
79498241 actual_type->id == TypeTableEntryIdNumLitFloat)
79508242 {
7951 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error.child_type, value);
8243 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
79528244 if (type_is_invalid(cast1->value.type))
79538245 return ira->codegen->invalid_instruction;
79548246
......@@ -8017,21 +8309,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
80178309 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
80188310 }
80198311
8020 // explicit cast from %void to integer type which can fit it
8312 // explicit cast from T!void to integer type which can fit it
80218313 bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
8022 !type_has_bits(actual_type->data.error.child_type);
8023 bool actual_type_is_pure_err = actual_type->id == TypeTableEntryIdPureError;
8024 if ((actual_type_is_void_err || actual_type_is_pure_err) &&
8025 wanted_type->id == TypeTableEntryIdInt)
8026 {
8314 !type_has_bits(actual_type->data.error_union.payload_type);
8315 bool actual_type_is_err_set = actual_type->id == TypeTableEntryIdErrorSet;
8316 if ((actual_type_is_void_err || actual_type_is_err_set) && wanted_type->id == TypeTableEntryIdInt) {
80278317 return ir_analyze_err_to_int(ira, source_instr, value, wanted_type);
80288318 }
80298319
8030 // explicit cast from integer to pure error
8031 if (wanted_type->id == TypeTableEntryIdPureError && actual_type->id == TypeTableEntryIdInt &&
8320 // explicit cast from integer to error set
8321 if (wanted_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdInt &&
80328322 !actual_type->data.integral.is_signed)
80338323 {
8034 return ir_analyze_int_to_err(ira, source_instr, value);
8324 return ir_analyze_int_to_err(ira, source_instr, value, wanted_type);
80358325 }
80368326
80378327 // explicit cast from integer to enum type with no payload
......@@ -8524,7 +8814,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
85248814 case TypeTableEntryIdMetaType:
85258815 case TypeTableEntryIdVoid:
85268816 case TypeTableEntryIdPointer:
8527 case TypeTableEntryIdPureError:
8817 case TypeTableEntryIdErrorSet:
85288818 case TypeTableEntryIdFn:
85298819 case TypeTableEntryIdOpaque:
85308820 case TypeTableEntryIdNamespace:
......@@ -9312,7 +9602,7 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
93129602 case TypeTableEntryIdInt:
93139603 case TypeTableEntryIdFloat:
93149604 case TypeTableEntryIdVoid:
9315 case TypeTableEntryIdPureError:
9605 case TypeTableEntryIdErrorSet:
93169606 case TypeTableEntryIdFn:
93179607 return VarClassRequiredAny;
93189608 case TypeTableEntryIdNumLitFloat:
......@@ -9338,7 +9628,7 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
93389628 case TypeTableEntryIdMaybe:
93399629 return get_var_class_required(type_entry->data.maybe.child_type);
93409630 case TypeTableEntryIdErrorUnion:
9341 return get_var_class_required(type_entry->data.error.child_type);
9631 return get_var_class_required(type_entry->data.error_union.payload_type);
93429632
93439633 case TypeTableEntryIdStruct:
93449634 case TypeTableEntryIdEnum:
......@@ -9573,7 +9863,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
95739863 case TypeTableEntryIdNullLit:
95749864 case TypeTableEntryIdMaybe:
95759865 case TypeTableEntryIdErrorUnion:
9576 case TypeTableEntryIdPureError:
9866 case TypeTableEntryIdErrorSet:
95779867 case TypeTableEntryIdNamespace:
95789868 case TypeTableEntryIdBlock:
95799869 case TypeTableEntryIdBoundFn:
......@@ -9596,7 +9886,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
95969886 case TypeTableEntryIdNullLit:
95979887 case TypeTableEntryIdMaybe:
95989888 case TypeTableEntryIdErrorUnion:
9599 case TypeTableEntryIdPureError:
9889 case TypeTableEntryIdErrorSet:
96009890 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
96019891 case TypeTableEntryIdNamespace:
96029892 case TypeTableEntryIdBlock:
......@@ -9630,6 +9920,24 @@ static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
96309920 return nullable_type;
96319921}
96329922
9923static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,
9924 IrInstructionErrorUnion *instruction)
9925{
9926 TypeTableEntry *err_set_type = ir_resolve_type(ira, instruction->err_set->other);
9927 if (type_is_invalid(err_set_type))
9928 return ira->codegen->builtin_types.entry_invalid;
9929
9930 TypeTableEntry *payload_type = ir_resolve_type(ira, instruction->payload->other);
9931 if (type_is_invalid(payload_type))
9932 return ira->codegen->builtin_types.entry_invalid;
9933
9934 TypeTableEntry *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
9935
9936 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
9937 out_val->data.x_type = result_type;
9938 return ira->codegen->builtin_types.entry_type;
9939}
9940
96339941static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
96349942 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)
96359943{
......@@ -10114,7 +10422,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1011410422 TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
1011510423 ir_add_alloca(ira, new_call_instruction, return_type);
1011610424
10117 if (return_type->id == TypeTableEntryIdPureError || return_type->id == TypeTableEntryIdErrorUnion) {
10425 if (return_type->id == TypeTableEntryIdErrorSet || return_type->id == TypeTableEntryIdErrorUnion) {
1011810426 parent_fn_entry->calls_errorable_function = true;
1011910427 }
1012010428
......@@ -10124,7 +10432,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1012410432 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
1012510433 assert(fn_type_id->return_type != nullptr);
1012610434 assert(parent_fn_entry != nullptr);
10127 if (fn_type_id->return_type->id == TypeTableEntryIdPureError || fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) {
10435 if (fn_type_id->return_type->id == TypeTableEntryIdErrorSet || fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) {
1012810436 parent_fn_entry->calls_errorable_function = true;
1012910437 }
1013010438
......@@ -10243,58 +10551,6 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
1024310551 }
1024410552}
1024510553
10246static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
10247 assert(un_op_instruction->op_id == IrUnOpError);
10248 IrInstruction *value = un_op_instruction->value->other;
10249
10250 TypeTableEntry *meta_type = ir_resolve_type(ira, value);
10251 if (type_is_invalid(meta_type))
10252 return ira->codegen->builtin_types.entry_invalid;
10253
10254
10255 switch (meta_type->id) {
10256 case TypeTableEntryIdInvalid: // handled above
10257 zig_unreachable();
10258
10259 case TypeTableEntryIdVoid:
10260 case TypeTableEntryIdBool:
10261 case TypeTableEntryIdInt:
10262 case TypeTableEntryIdFloat:
10263 case TypeTableEntryIdPointer:
10264 case TypeTableEntryIdArray:
10265 case TypeTableEntryIdStruct:
10266 case TypeTableEntryIdMaybe:
10267 case TypeTableEntryIdErrorUnion:
10268 case TypeTableEntryIdPureError:
10269 case TypeTableEntryIdEnum:
10270 case TypeTableEntryIdUnion:
10271 case TypeTableEntryIdFn:
10272 case TypeTableEntryIdBoundFn:
10273 {
10274 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
10275 TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type);
10276 out_val->data.x_type = result_type;
10277 return ira->codegen->builtin_types.entry_type;
10278 }
10279 case TypeTableEntryIdMetaType:
10280 case TypeTableEntryIdNumLitFloat:
10281 case TypeTableEntryIdNumLitInt:
10282 case TypeTableEntryIdUndefLit:
10283 case TypeTableEntryIdNullLit:
10284 case TypeTableEntryIdNamespace:
10285 case TypeTableEntryIdBlock:
10286 case TypeTableEntryIdUnreachable:
10287 case TypeTableEntryIdVar:
10288 case TypeTableEntryIdArgTuple:
10289 case TypeTableEntryIdOpaque:
10290 ir_add_error_node(ira, un_op_instruction->base.source_node,
10291 buf_sprintf("unable to wrap type '%s' in error type", buf_ptr(&meta_type->name)));
10292 return ira->codegen->builtin_types.entry_invalid;
10293 }
10294 zig_unreachable();
10295}
10296
10297
1029810554static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
1029910555 IrInstruction *value = un_op_instruction->value->other;
1030010556
......@@ -10350,7 +10606,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
1035010606 case TypeTableEntryIdNullLit:
1035110607 case TypeTableEntryIdMaybe:
1035210608 case TypeTableEntryIdErrorUnion:
10353 case TypeTableEntryIdPureError:
10609 case TypeTableEntryIdErrorSet:
1035410610 case TypeTableEntryIdEnum:
1035510611 case TypeTableEntryIdUnion:
1035610612 case TypeTableEntryIdFn:
......@@ -10460,8 +10716,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
1046010716 return ir_analyze_dereference(ira, un_op_instruction);
1046110717 case IrUnOpMaybe:
1046210718 return ir_analyze_maybe(ira, un_op_instruction);
10463 case IrUnOpError:
10464 return ir_analyze_unary_prefix_op_err(ira, un_op_instruction);
1046510719 }
1046610720 zig_unreachable();
1046710721}
......@@ -11083,6 +11337,17 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
1108311337 zig_unreachable();
1108411338}
1108511339
11340static ErrorTableEntry *find_err_table_entry(TypeTableEntry *err_set_type, Buf *field_name) {
11341 assert(err_set_type->id == TypeTableEntryIdErrorSet);
11342 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
11343 ErrorTableEntry *err_table_entry = err_set_type->data.error_set.errors[i];
11344 if (buf_eql_buf(&err_table_entry->name, field_name)) {
11345 return err_table_entry;
11346 }
11347 }
11348 return nullptr;
11349}
11350
1108611351static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFieldPtr *field_ptr_instruction) {
1108711352 IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other;
1108811353 if (type_is_invalid(container_ptr->value.type))
......@@ -11224,23 +11489,49 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1122411489 buf_sprintf("container '%s' has no member called '%s'",
1122511490 buf_ptr(&child_type->name), buf_ptr(field_name)));
1122611491 return ira->codegen->builtin_types.entry_invalid;
11227 } else if (child_type->id == TypeTableEntryIdPureError) {
11228 auto err_table_entry = ira->codegen->error_table.maybe_get(field_name);
11229 if (err_table_entry) {
11230 ConstExprValue *const_val = create_const_vals(1);
11231 const_val->special = ConstValSpecialStatic;
11232 const_val->type = child_type;
11233 const_val->data.x_pure_err = err_table_entry->value;
11234
11235 bool ptr_is_const = true;
11236 bool ptr_is_volatile = false;
11237 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val,
11238 child_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11492 } else if (child_type->id == TypeTableEntryIdErrorSet) {
11493 ErrorTableEntry *err_entry;
11494 TypeTableEntry *err_set_type;
11495 if (child_type == ira->codegen->builtin_types.entry_global_error_set) {
11496 auto existing_entry = ira->codegen->error_table.maybe_get(field_name);
11497 if (existing_entry) {
11498 err_entry = existing_entry->value;
11499 } else {
11500 err_entry = allocate<ErrorTableEntry>(1);
11501 err_entry->decl_node = field_ptr_instruction->base.source_node;
11502 buf_init_from_buf(&err_entry->name, field_name);
11503 size_t error_value_count = ira->codegen->errors_by_index.length;
11504 assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count));
11505 err_entry->value = error_value_count;
11506 ira->codegen->errors_by_index.append(err_entry);
11507 ira->codegen->err_enumerators.append(ZigLLVMCreateDebugEnumerator(ira->codegen->dbuilder,
11508 buf_ptr(field_name), error_value_count));
11509 ira->codegen->error_table.put(field_name, err_entry);
11510 }
11511 if (err_entry->set_with_only_this_in_it == nullptr) {
11512 err_entry->set_with_only_this_in_it = make_err_set_with_one_item(ira->codegen,
11513 field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node,
11514 err_entry);
11515 }
11516 err_set_type = err_entry->set_with_only_this_in_it;
11517 } else {
11518 ErrorTableEntry *err_entry = find_err_table_entry(child_type, field_name);
11519 if (err_entry == nullptr) {
11520 ir_add_error(ira, &field_ptr_instruction->base,
11521 buf_sprintf("no error named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&child_type->name)));
11522 return ira->codegen->builtin_types.entry_invalid;
11523 }
11524 err_set_type = child_type;
1123911525 }
11526 ConstExprValue *const_val = create_const_vals(1);
11527 const_val->special = ConstValSpecialStatic;
11528 const_val->type = err_set_type;
11529 const_val->data.x_err_set = err_entry;
1124011530
11241 ir_add_error(ira, &field_ptr_instruction->base,
11242 buf_sprintf("use of undeclared error value '%s'", buf_ptr(field_name)));
11243 return ira->codegen->builtin_types.entry_invalid;
11531 bool ptr_is_const = true;
11532 bool ptr_is_volatile = false;
11533 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val,
11534 err_set_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
1124411535 } else if (child_type->id == TypeTableEntryIdInt) {
1124511536 if (buf_eql_str(field_name, "bit_count")) {
1124611537 bool ptr_is_const = true;
......@@ -11323,11 +11614,18 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1132311614 return ira->codegen->builtin_types.entry_invalid;
1132411615 }
1132511616 } else if (child_type->id == TypeTableEntryIdErrorUnion) {
11326 if (buf_eql_str(field_name, "Child")) {
11617 if (buf_eql_str(field_name, "Payload")) {
11618 bool ptr_is_const = true;
11619 bool ptr_is_volatile = false;
11620 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11621 create_const_type(ira->codegen, child_type->data.error_union.payload_type),
11622 ira->codegen->builtin_types.entry_type,
11623 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11624 } else if (buf_eql_str(field_name, "ErrorSet")) {
1132711625 bool ptr_is_const = true;
1132811626 bool ptr_is_volatile = false;
1132911627 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11330 create_const_type(ira->codegen, child_type->data.error.child_type),
11628 create_const_type(ira->codegen, child_type->data.error_union.err_set_type),
1133111629 ira->codegen->builtin_types.entry_type,
1133211630 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
1133311631 } else {
......@@ -11514,7 +11812,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
1151411812 case TypeTableEntryIdStruct:
1151511813 case TypeTableEntryIdMaybe:
1151611814 case TypeTableEntryIdErrorUnion:
11517 case TypeTableEntryIdPureError:
11815 case TypeTableEntryIdErrorSet:
1151811816 case TypeTableEntryIdEnum:
1151911817 case TypeTableEntryIdUnion:
1152011818 case TypeTableEntryIdFn:
......@@ -11781,7 +12079,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1178112079 case TypeTableEntryIdNumLitInt:
1178212080 case TypeTableEntryIdMaybe:
1178312081 case TypeTableEntryIdErrorUnion:
11784 case TypeTableEntryIdPureError:
12082 case TypeTableEntryIdErrorSet:
1178512083 case TypeTableEntryIdEnum:
1178612084 case TypeTableEntryIdUnion:
1178712085 case TypeTableEntryIdFn:
......@@ -11889,7 +12187,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
1188912187 case TypeTableEntryIdNumLitInt:
1189012188 case TypeTableEntryIdMaybe:
1189112189 case TypeTableEntryIdErrorUnion:
11892 case TypeTableEntryIdPureError:
12190 case TypeTableEntryIdErrorSet:
1189312191 case TypeTableEntryIdEnum:
1189412192 case TypeTableEntryIdUnion:
1189512193 case TypeTableEntryIdFn:
......@@ -11942,7 +12240,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
1194212240 case TypeTableEntryIdStruct:
1194312241 case TypeTableEntryIdMaybe:
1194412242 case TypeTableEntryIdErrorUnion:
11945 case TypeTableEntryIdPureError:
12243 case TypeTableEntryIdErrorSet:
1194612244 case TypeTableEntryIdEnum:
1194712245 case TypeTableEntryIdUnion:
1194812246 case TypeTableEntryIdFn:
......@@ -12277,7 +12575,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1227712575 case TypeTableEntryIdPointer:
1227812576 case TypeTableEntryIdFn:
1227912577 case TypeTableEntryIdNamespace:
12280 case TypeTableEntryIdPureError:
12578 case TypeTableEntryIdErrorSet:
1228112579 if (pointee_val) {
1228212580 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
1228312581 copy_const_val(out_val, pointee_val, true);
......@@ -12347,8 +12645,6 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1234712645 return target_type;
1234812646 }
1234912647 case TypeTableEntryIdErrorUnion:
12350 // see https://github.com/andrewrk/zig/issues/632
12351 zig_panic("TODO switch on error union");
1235212648 case TypeTableEntryIdUnreachable:
1235312649 case TypeTableEntryIdArray:
1235412650 case TypeTableEntryIdStruct:
......@@ -12873,7 +13169,7 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
1287313169 case TypeTableEntryIdNullLit:
1287413170 case TypeTableEntryIdMaybe:
1287513171 case TypeTableEntryIdErrorUnion:
12876 case TypeTableEntryIdPureError:
13172 case TypeTableEntryIdErrorSet:
1287713173 case TypeTableEntryIdUnion:
1287813174 case TypeTableEntryIdFn:
1287913175 case TypeTableEntryIdNamespace:
......@@ -12961,7 +13257,7 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc
1296113257 TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
1296213258 TypeTableEntry *str_type = get_slice_type(ira->codegen, u8_ptr_type);
1296313259 if (casted_value->value.special == ConstValSpecialStatic) {
12964 ErrorTableEntry *err = casted_value->value.data.x_pure_err;
13260 ErrorTableEntry *err = casted_value->value.data.x_err_set;
1296513261 if (!err->cached_error_name_val) {
1296613262 ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name);
1296713263 err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true);
......@@ -14106,7 +14402,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
1410614402 case TypeTableEntryIdStruct:
1410714403 case TypeTableEntryIdMaybe:
1410814404 case TypeTableEntryIdErrorUnion:
14109 case TypeTableEntryIdPureError:
14405 case TypeTableEntryIdErrorSet:
1411014406 case TypeTableEntryIdEnum:
1411114407 case TypeTableEntryIdUnion:
1411214408 case TypeTableEntryIdFn:
......@@ -14239,7 +14535,7 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc
1423914535
1424014536 ir_build_test_err_from(&ira->new_irb, &instruction->base, value);
1424114537 return ira->codegen->builtin_types.entry_bool;
14242 } else if (type_entry->id == TypeTableEntryIdPureError) {
14538 } else if (type_entry->id == TypeTableEntryIdErrorSet) {
1424314539 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1424414540 out_val->data.x_bool = true;
1424514541 return ira->codegen->builtin_types.entry_bool;
......@@ -14275,13 +14571,13 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
1427514571 assert(err);
1427614572
1427714573 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
14278 out_val->data.x_pure_err = err;
14279 return ira->codegen->builtin_types.entry_pure_error;
14574 out_val->data.x_err_set = err;
14575 return type_entry->data.error_union.err_set_type;
1428014576 }
1428114577 }
1428214578
1428314579 ir_build_unwrap_err_code_from(&ira->new_irb, &instruction->base, value);
14284 return ira->codegen->builtin_types.entry_pure_error;
14580 return type_entry->data.error_union.err_set_type;
1428514581 } else {
1428614582 ir_add_error(ira, value,
1428714583 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
......@@ -14305,10 +14601,10 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
1430514601 if (type_is_invalid(type_entry)) {
1430614602 return ira->codegen->builtin_types.entry_invalid;
1430714603 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
14308 TypeTableEntry *child_type = type_entry->data.error.child_type;
14309 TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
14604 TypeTableEntry *payload_type = type_entry->data.error_union.payload_type;
14605 TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
1431014606 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14311 get_abi_alignment(ira->codegen, child_type), 0, 0);
14607 get_abi_alignment(ira->codegen, payload_type), 0, 0);
1431214608 if (instr_is_comptime(value)) {
1431314609 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
1431414610 if (!ptr_val)
......@@ -14343,6 +14639,12 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
1434314639 AstNode *proto_node = instruction->base.source_node;
1434414640 assert(proto_node->type == NodeTypeFnProto);
1434514641
14642 if (proto_node->data.fn_proto.auto_err_set) {
14643 ir_add_error(ira, &instruction->base,
14644 buf_sprintf("inferring error set of return type valid only for function definitions"));
14645 return ira->codegen->builtin_types.entry_invalid;
14646 }
14647
1434614648 FnTypeId fn_type_id = {0};
1434714649 init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
1434814650
......@@ -14468,6 +14770,71 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1446814770 }
1446914771 }
1447014772 }
14773 } else if (switch_type->id == TypeTableEntryIdErrorSet) {
14774 FnTableEntry *infer_fn = switch_type->data.error_set.infer_fn;
14775 if (infer_fn != nullptr) {
14776 if (infer_fn->anal_state == FnAnalStateInvalid) {
14777 return ira->codegen->builtin_types.entry_invalid;
14778 } else if (infer_fn->anal_state == FnAnalStateReady) {
14779 analyze_fn_body(ira->codegen, infer_fn);
14780 if (switch_type->data.error_set.infer_fn != nullptr) {
14781 assert(ira->codegen->errors.length != 0);
14782 return ira->codegen->builtin_types.entry_invalid;
14783 }
14784 } else {
14785 ir_add_error(ira, &instruction->base,
14786 buf_sprintf("cannot switch on inferred error set '%s': function '%s' not fully analyzed yet",
14787 buf_ptr(&switch_type->name), buf_ptr(&switch_type->data.error_set.infer_fn->symbol_name)));
14788 return ira->codegen->builtin_types.entry_invalid;
14789 }
14790 }
14791
14792 AstNode **field_prev_uses = allocate<AstNode *>(ira->codegen->errors_by_index.length);
14793
14794 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
14795 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
14796
14797 IrInstruction *start_value = range->start->other;
14798 if (type_is_invalid(start_value->value.type))
14799 return ira->codegen->builtin_types.entry_invalid;
14800
14801 IrInstruction *end_value = range->end->other;
14802 if (type_is_invalid(end_value->value.type))
14803 return ira->codegen->builtin_types.entry_invalid;
14804
14805 assert(start_value->value.type->id == TypeTableEntryIdErrorSet);
14806 uint32_t start_index = start_value->value.data.x_err_set->value;
14807
14808 assert(end_value->value.type->id == TypeTableEntryIdErrorSet);
14809 uint32_t end_index = end_value->value.data.x_err_set->value;
14810
14811 if (start_index != end_index) {
14812 ir_add_error(ira, end_value, buf_sprintf("ranges not allowed when switching on errors"));
14813 return ira->codegen->builtin_types.entry_invalid;
14814 }
14815
14816 AstNode *prev_node = field_prev_uses[start_index];
14817 if (prev_node != nullptr) {
14818 Buf *err_name = &ira->codegen->errors_by_index.at(start_index)->name;
14819 ErrorMsg *msg = ir_add_error(ira, start_value,
14820 buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&switch_type->name), buf_ptr(err_name)));
14821 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here"));
14822 }
14823 field_prev_uses[start_index] = start_value->source_node;
14824 }
14825 if (!instruction->have_else_prong) {
14826 for (uint32_t i = 0; i < switch_type->data.error_set.err_count; i += 1) {
14827 ErrorTableEntry *err_entry = switch_type->data.error_set.errors[i];
14828
14829 AstNode *prev_node = field_prev_uses[err_entry->value];
14830 if (prev_node == nullptr) {
14831 ir_add_error(ira, &instruction->base,
14832 buf_sprintf("error.%s not handled in switch", buf_ptr(&err_entry->name)));
14833 }
14834 }
14835 }
14836
14837 free(field_prev_uses);
1447114838 } else if (switch_type->id == TypeTableEntryIdInt) {
1447214839 RangeSet rs = {0};
1447314840 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
......@@ -14760,7 +15127,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1476015127 zig_panic("TODO buf_write_value_bytes maybe type");
1476115128 case TypeTableEntryIdErrorUnion:
1476215129 zig_panic("TODO buf_write_value_bytes error union");
14763 case TypeTableEntryIdPureError:
15130 case TypeTableEntryIdErrorSet:
1476415131 zig_panic("TODO buf_write_value_bytes pure error type");
1476515132 case TypeTableEntryIdEnum:
1476615133 zig_panic("TODO buf_write_value_bytes enum type");
......@@ -14818,7 +15185,7 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1481815185 zig_panic("TODO buf_read_value_bytes maybe type");
1481915186 case TypeTableEntryIdErrorUnion:
1482015187 zig_panic("TODO buf_read_value_bytes error union");
14821 case TypeTableEntryIdPureError:
15188 case TypeTableEntryIdErrorSet:
1482215189 zig_panic("TODO buf_read_value_bytes pure error type");
1482315190 case TypeTableEntryIdEnum:
1482415191 zig_panic("TODO buf_read_value_bytes enum type");
......@@ -15429,6 +15796,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1542915796 return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction);
1543015797 case IrInstructionIdErrorReturnTrace:
1543115798 return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction);
15799 case IrInstructionIdErrorUnion:
15800 return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction);
1543215801 }
1543315802 zig_unreachable();
1543415803}
......@@ -15614,6 +15983,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1561415983 case IrInstructionIdArgType:
1561515984 case IrInstructionIdTagType:
1561615985 case IrInstructionIdErrorReturnTrace:
15986 case IrInstructionIdErrorUnion:
1561715987 return false;
1561815988 case IrInstructionIdAsm:
1561915989 {
src/ir_print.cpp+8-2
......@@ -148,8 +148,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
148148 return "*";
149149 case IrUnOpMaybe:
150150 return "?";
151 case IrUnOpError:
152 return "%";
153151 }
154152 zig_unreachable();
155153}
......@@ -1004,6 +1002,11 @@ static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTr
10041002 fprintf(irp->f, "@errorReturnTrace()");
10051003}
10061004
1005static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruction) {
1006 ir_print_other_instruction(irp, instruction->err_set);
1007 fprintf(irp->f, "!");
1008 ir_print_other_instruction(irp, instruction->payload);
1009}
10071010
10081011static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
10091012 ir_print_prefix(irp, instruction);
......@@ -1322,6 +1325,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
13221325 case IrInstructionIdErrorReturnTrace:
13231326 ir_print_error_return_trace(irp, (IrInstructionErrorReturnTrace *)instruction);
13241327 break;
1328 case IrInstructionIdErrorUnion:
1329 ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction);
1330 break;
13251331 }
13261332 fprintf(irp->f, "\n");
13271333}
src/parser.cpp+50-37
......@@ -221,6 +221,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bo
221221static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory);
222222static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory);
223223static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index);
224static AstNode *ast_parse_symbol(ParseContext *pc, size_t *token_index);
224225
225226static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
226227 if (token->id == token_id) {
......@@ -651,8 +652,9 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
651652}
652653
653654/*
654PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl | ("continue" option(":" Symbol))
655PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
655656KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable"
657ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
656658*/
657659static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
658660 Token *token = &pc->tokens->at(*token_index);
......@@ -716,9 +718,31 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
716718 *token_index += 1;
717719 return node;
718720 } else if (token->id == TokenIdKeywordError) {
719 AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
720 *token_index += 1;
721 return node;
721 Token *next_token = &pc->tokens->at(*token_index + 1);
722 if (next_token->id == TokenIdLBrace) {
723 AstNode *node = ast_create_node(pc, NodeTypeErrorSetDecl, token);
724 *token_index += 2;
725 for (;;) {
726 Token *item_tok = &pc->tokens->at(*token_index);
727 if (item_tok->id == TokenIdRBrace) {
728 *token_index += 1;
729 return node;
730 } else if (item_tok->id == TokenIdSymbol) {
731 AstNode *symbol_node = ast_parse_symbol(pc, token_index);
732 node->data.err_set_decl.decls.append(symbol_node);
733 Token *opt_comma_tok = &pc->tokens->at(*token_index);
734 if (opt_comma_tok->id == TokenIdComma) {
735 *token_index += 1;
736 }
737 } else {
738 ast_invalid_token_error(pc, item_tok);
739 }
740 }
741 } else {
742 AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
743 *token_index += 1;
744 return node;
745 }
722746 } else if (token->id == TokenIdAtSign) {
723747 *token_index += 1;
724748 Token *name_tok = &pc->tokens->at(*token_index);
......@@ -950,7 +974,6 @@ static PrefixOp tok_to_prefix_op(Token *token) {
950974 case TokenIdTilde: return PrefixOpBinNot;
951975 case TokenIdStar: return PrefixOpDereference;
952976 case TokenIdMaybe: return PrefixOpMaybe;
953 case TokenIdPercent: return PrefixOpError;
954977 case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe;
955978 case TokenIdStarStar: return PrefixOpDereference;
956979 default: return PrefixOpInvalid;
......@@ -998,7 +1021,7 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) {
9981021
9991022/*
10001023PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
1001PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%" | "try"
1024PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try"
10021025*/
10031026static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
10041027 Token *token = &pc->tokens->at(*token_index);
......@@ -1043,12 +1066,13 @@ static BinOpType tok_to_mult_op(Token *token) {
10431066 case TokenIdStarStar: return BinOpTypeArrayMult;
10441067 case TokenIdSlash: return BinOpTypeDiv;
10451068 case TokenIdPercent: return BinOpTypeMod;
1069 case TokenIdBang: return BinOpTypeErrorUnion;
10461070 default: return BinOpTypeInvalid;
10471071 }
10481072}
10491073
10501074/*
1051MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
1075MultiplyOperator = "!" | "*" | "/" | "%" | "**" | "*%"
10521076*/
10531077static BinOpType ast_parse_mult_op(ParseContext *pc, size_t *token_index, bool mandatory) {
10541078 Token *token = &pc->tokens->at(*token_index);
......@@ -2240,7 +2264,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
22402264}
22412265
22422266/*
2243FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr
2267FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
22442268*/
22452269static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
22462270 Token *first_token = &pc->tokens->at(*token_index);
......@@ -2315,6 +2339,21 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
23152339 ast_eat_token(pc, token_index, TokenIdRParen);
23162340 next_token = &pc->tokens->at(*token_index);
23172341 }
2342 if (next_token->id == TokenIdKeywordError) {
2343 Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1);
2344 if (maybe_lbrace_tok->id == TokenIdLBrace) {
2345 *token_index += 1;
2346 node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token);
2347 return node;
2348 }
2349
2350 return node;
2351 }
2352 if (next_token->id == TokenIdBang) {
2353 *token_index += 1;
2354 node->data.fn_proto.auto_err_set = true;
2355 next_token = &pc->tokens->at(*token_index);
2356 }
23182357 node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true);
23192358
23202359 return node;
......@@ -2559,26 +2598,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
25592598 return node;
25602599}
25612600
2562/*
2563ErrorValueDecl : "error" "Symbol" ";"
2564*/
2565static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index) {
2566 Token *first_token = &pc->tokens->at(*token_index);
2567
2568 if (first_token->id != TokenIdKeywordError) {
2569 return nullptr;
2570 }
2571 *token_index += 1;
2572
2573 Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
2574 ast_eat_token(pc, token_index, TokenIdSemicolon);
2575
2576 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);
2577 node->data.error_value_decl.name = token_buf(name_tok);
2578
2579 return node;
2580}
2581
25822601/*
25832602TestDecl = "test" String Block
25842603*/
......@@ -2611,12 +2630,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
26112630 continue;
26122631 }
26132632
2614 AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index);
2615 if (error_value_node) {
2616 top_level_decls->append(error_value_node);
2617 continue;
2618 }
2619
26202633 AstNode *test_decl_node = ast_parse_test_decl_node(pc, token_index);
26212634 if (test_decl_node) {
26222635 top_level_decls->append(test_decl_node);
......@@ -2744,9 +2757,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
27442757 visit_field(&node->data.variable_declaration.align_expr, visit, context);
27452758 visit_field(&node->data.variable_declaration.section_expr, visit, context);
27462759 break;
2747 case NodeTypeErrorValueDecl:
2748 // none
2749 break;
27502760 case NodeTypeTestDecl:
27512761 visit_field(&node->data.test_decl.body, visit, context);
27522762 break;
......@@ -2899,5 +2909,8 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
28992909 visit_field(&node->data.addr_of_expr.align_expr, visit, context);
29002910 visit_field(&node->data.addr_of_expr.op_expr, visit, context);
29012911 break;
2912 case NodeTypeErrorSetDecl:
2913 visit_node_list(&node->data.err_set_decl.decls, visit, context);
2914 break;
29022915 }
29032916}
src/zig_llvm.cpp+4
......@@ -437,6 +437,10 @@ unsigned ZigLLVMTag_DW_structure_type(void) {
437437 return dwarf::DW_TAG_structure_type;
438438}
439439
440unsigned ZigLLVMTag_DW_enumeration_type(void) {
441 return dwarf::DW_TAG_enumeration_type;
442}
443
440444unsigned ZigLLVMTag_DW_union_type(void) {
441445 return dwarf::DW_TAG_union_type;
442446}
src/zig_llvm.h+1
......@@ -133,6 +133,7 @@ ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed_char(void);
133133ZIG_EXTERN_C unsigned ZigLLVMLang_DW_LANG_C99(void);
134134ZIG_EXTERN_C unsigned ZigLLVMTag_DW_variable(void);
135135ZIG_EXTERN_C unsigned ZigLLVMTag_DW_structure_type(void);
136ZIG_EXTERN_C unsigned ZigLLVMTag_DW_enumeration_type(void);
136137ZIG_EXTERN_C unsigned ZigLLVMTag_DW_union_type(void);
137138
138139ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved);
std/debug/index.zig+34-46
......@@ -10,15 +10,6 @@ const builtin = @import("builtin");
1010
1111pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator;
1212
13error MissingDebugInfo;
14error InvalidDebugInfo;
15error UnsupportedDebugInfo;
16error UnknownObjectFormat;
17error TodoSupportCoffDebugInfo;
18error TodoSupportMachoDebugInfo;
19error TodoSupportCOFFDebugInfo;
20
21
2213/// Tries to write to stderr, unbuffered, and ignores any error returned.
2314/// Does not append a newline.
2415/// TODO atomic/multithread support
......@@ -29,7 +20,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {
2920 const stderr = getStderrStream() catch return;
3021 stderr.print(fmt, args) catch return;
3122}
32fn getStderrStream() %&io.OutStream {
23fn getStderrStream() !&io.OutStream {
3324 if (stderr_stream) |st| {
3425 return st;
3526 } else {
......@@ -42,7 +33,7 @@ fn getStderrStream() %&io.OutStream {
4233}
4334
4435var self_debug_info: ?&ElfStackTrace = null;
45pub fn getSelfDebugInfo() %&ElfStackTrace {
36pub fn getSelfDebugInfo() !&ElfStackTrace {
4637 if (self_debug_info) |info| {
4738 return info;
4839 } else {
......@@ -149,11 +140,8 @@ const WHITE = "\x1b[37;1m";
149140const DIM = "\x1b[2m";
150141const RESET = "\x1b[0m";
151142
152error PathNotFound;
153error InvalidDebugInfo;
154
155143pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator,
156 debug_info: &ElfStackTrace, tty_color: bool) %void
144 debug_info: &ElfStackTrace, tty_color: bool) !void
157145{
158146 var frame_index: usize = undefined;
159147 var frames_left: usize = undefined;
......@@ -175,7 +163,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.O
175163}
176164
177165pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator,
178 debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) %void
166 debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) !void
179167{
180168 var ignored_count: usize = 0;
181169
......@@ -191,7 +179,7 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat
191179 }
192180}
193181
194fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) %void {
182fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) !void {
195183 if (builtin.os == builtin.Os.windows) {
196184 return error.UnsupportedDebugInfo;
197185 }
......@@ -232,7 +220,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a
232220 }
233221}
234222
235pub fn openSelfDebugInfo(allocator: &mem.Allocator) %&ElfStackTrace {
223pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace {
236224 switch (builtin.object_format) {
237225 builtin.ObjectFormat.elf => {
238226 const st = try allocator.create(ElfStackTrace);
......@@ -276,7 +264,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) %&ElfStackTrace {
276264 }
277265}
278266
279fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) %void {
267fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) !void {
280268 var f = try io.File.openRead(line_info.file_name, allocator);
281269 defer f.close();
282270 // TODO fstat and make sure that the file has the correct size
......@@ -324,7 +312,7 @@ pub const ElfStackTrace = struct {
324312 return self.abbrev_table_list.allocator;
325313 }
326314
327 pub fn readString(self: &ElfStackTrace) %[]u8 {
315 pub fn readString(self: &ElfStackTrace) ![]u8 {
328316 var in_file_stream = io.FileInStream.init(&self.self_exe_file);
329317 const in_stream = &in_file_stream.stream;
330318 return readStringRaw(self.allocator(), in_stream);
......@@ -387,7 +375,7 @@ const Constant = struct {
387375 payload: []u8,
388376 signed: bool,
389377
390 fn asUnsignedLe(self: &const Constant) %u64 {
378 fn asUnsignedLe(self: &const Constant) !u64 {
391379 if (self.payload.len > @sizeOf(u64))
392380 return error.InvalidDebugInfo;
393381 if (self.signed)
......@@ -414,7 +402,7 @@ const Die = struct {
414402 return null;
415403 }
416404
417 fn getAttrAddr(self: &const Die, id: u64) %u64 {
405 fn getAttrAddr(self: &const Die, id: u64) !u64 {
418406 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
419407 return switch (*form_value) {
420408 FormValue.Address => |value| value,
......@@ -422,7 +410,7 @@ const Die = struct {
422410 };
423411 }
424412
425 fn getAttrSecOffset(self: &const Die, id: u64) %u64 {
413 fn getAttrSecOffset(self: &const Die, id: u64) !u64 {
426414 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
427415 return switch (*form_value) {
428416 FormValue.Const => |value| value.asUnsignedLe(),
......@@ -431,7 +419,7 @@ const Die = struct {
431419 };
432420 }
433421
434 fn getAttrUnsignedLe(self: &const Die, id: u64) %u64 {
422 fn getAttrUnsignedLe(self: &const Die, id: u64) !u64 {
435423 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
436424 return switch (*form_value) {
437425 FormValue.Const => |value| value.asUnsignedLe(),
......@@ -439,7 +427,7 @@ const Die = struct {
439427 };
440428 }
441429
442 fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) %[]u8 {
430 fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) ![]u8 {
443431 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
444432 return switch (*form_value) {
445433 FormValue.String => |value| value,
......@@ -512,7 +500,7 @@ const LineNumberProgram = struct {
512500 };
513501 }
514502
515 pub fn checkLineMatch(self: &LineNumberProgram) %?LineInfo {
503 pub fn checkLineMatch(self: &LineNumberProgram) !?LineInfo {
516504 if (self.target_address >= self.prev_address and self.target_address < self.address) {
517505 const file_entry = if (self.prev_file == 0) {
518506 return error.MissingDebugInfo;
......@@ -544,7 +532,7 @@ const LineNumberProgram = struct {
544532 }
545533};
546534
547fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) %[]u8 {
535fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) ![]u8 {
548536 var buf = ArrayList(u8).init(allocator);
549537 while (true) {
550538 const byte = try in_stream.readByte();
......@@ -555,58 +543,58 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) %[]u8 {
555543 return buf.toSlice();
556544}
557545
558fn getString(st: &ElfStackTrace, offset: u64) %[]u8 {
546fn getString(st: &ElfStackTrace, offset: u64) ![]u8 {
559547 const pos = st.debug_str.offset + offset;
560548 try st.self_exe_file.seekTo(pos);
561549 return st.readString();
562550}
563551
564fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %[]u8 {
552fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) ![]u8 {
565553 const buf = try global_allocator.alloc(u8, size);
566554 errdefer global_allocator.free(buf);
567555 if ((try in_stream.read(buf)) < size) return error.EndOfFile;
568556 return buf;
569557}
570558
571fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue {
559fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue {
572560 const buf = try readAllocBytes(allocator, in_stream, size);
573561 return FormValue { .Block = buf };
574562}
575563
576fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue {
564fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue {
577565 const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);
578566 return parseFormValueBlockLen(allocator, in_stream, block_len);
579567}
580568
581fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) %FormValue {
569fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) !FormValue {
582570 return FormValue { .Const = Constant {
583571 .signed = signed,
584572 .payload = try readAllocBytes(allocator, in_stream, size),
585573 }};
586574}
587575
588fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) %u64 {
576fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) !u64 {
589577 return if (is_64) try in_stream.readIntLe(u64)
590578 else u64(try in_stream.readIntLe(u32)) ;
591579}
592580
593fn parseFormValueTargetAddrSize(in_stream: &io.InStream) %u64 {
581fn parseFormValueTargetAddrSize(in_stream: &io.InStream) !u64 {
594582 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32))
595583 else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64)
596584 else unreachable;
597585}
598586
599fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue {
587fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue {
600588 const buf = try readAllocBytes(allocator, in_stream, size);
601589 return FormValue { .Ref = buf };
602590}
603591
604fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) %FormValue {
592fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) !FormValue {
605593 const block_len = try in_stream.readIntLe(T);
606594 return parseFormValueRefLen(allocator, in_stream, block_len);
607595}
608596
609fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) %FormValue {
597fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) !FormValue {
610598 return switch (form_id) {
611599 DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) },
612600 DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
......@@ -656,7 +644,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
656644 };
657645}
658646
659fn parseAbbrevTable(st: &ElfStackTrace) %AbbrevTable {
647fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable {
660648 const in_file = &st.self_exe_file;
661649 var in_file_stream = io.FileInStream.init(in_file);
662650 const in_stream = &in_file_stream.stream;
......@@ -688,7 +676,7 @@ fn parseAbbrevTable(st: &ElfStackTrace) %AbbrevTable {
688676
689677/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
690678/// seeks in the stream and parses it.
691fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) %&const AbbrevTable {
679fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable {
692680 for (st.abbrev_table_list.toSlice()) |*header| {
693681 if (header.offset == abbrev_offset) {
694682 return &header.table;
......@@ -710,7 +698,7 @@ fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&con
710698 return null;
711699}
712700
713fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) %Die {
701fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) !Die {
714702 const in_file = &st.self_exe_file;
715703 var in_file_stream = io.FileInStream.init(in_file);
716704 const in_stream = &in_file_stream.stream;
......@@ -732,7 +720,7 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) %
732720 return result;
733721}
734722
735fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) %LineInfo {
723fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) !LineInfo {
736724 const compile_unit_cwd = try compile_unit.die.getAttrString(st, DW.AT_comp_dir);
737725
738726 const in_file = &st.self_exe_file;
......@@ -910,7 +898,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
910898 return error.MissingDebugInfo;
911899}
912900
913fn scanAllCompileUnits(st: &ElfStackTrace) %void {
901fn scanAllCompileUnits(st: &ElfStackTrace) !void {
914902 const debug_info_end = st.debug_info.offset + st.debug_info.size;
915903 var this_unit_offset = st.debug_info.offset;
916904 var cu_index: usize = 0;
......@@ -986,7 +974,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) %void {
986974 }
987975}
988976
989fn findCompileUnit(st: &ElfStackTrace, target_address: u64) %&const CompileUnit {
977fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit {
990978 var in_file_stream = io.FileInStream.init(&st.self_exe_file);
991979 const in_stream = &in_file_stream.stream;
992980 for (st.compile_unit_list.toSlice()) |*compile_unit| {
......@@ -1022,7 +1010,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) %&const CompileUnit
10221010 return error.MissingDebugInfo;
10231011}
10241012
1025fn readInitialLength(in_stream: &io.InStream, is_64: &bool) %u64 {
1013fn readInitialLength(in_stream: &io.InStream, is_64: &bool) !u64 {
10261014 const first_32_bits = try in_stream.readIntLe(u32);
10271015 *is_64 = (first_32_bits == 0xffffffff);
10281016 if (*is_64) {
......@@ -1033,7 +1021,7 @@ fn readInitialLength(in_stream: &io.InStream, is_64: &bool) %u64 {
10331021 }
10341022}
10351023
1036fn readULeb128(in_stream: &io.InStream) %u64 {
1024fn readULeb128(in_stream: &io.InStream) !u64 {
10371025 var result: u64 = 0;
10381026 var shift: usize = 0;
10391027
......@@ -1054,7 +1042,7 @@ fn readULeb128(in_stream: &io.InStream) %u64 {
10541042 }
10551043}
10561044
1057fn readILeb128(in_stream: &io.InStream) %i64 {
1045fn readILeb128(in_stream: &io.InStream) !i64 {
10581046 var result: i64 = 0;
10591047 var shift: usize = 0;
10601048
std/os/index.zig+43-77
......@@ -57,25 +57,10 @@ const ArrayList = std.ArrayList;
5757const Buffer = std.Buffer;
5858const math = std.math;
5959
60error SystemResources;
61error AccessDenied;
62error InvalidExe;
63error FileSystem;
64error IsDir;
65error FileNotFound;
66error FileBusy;
67error PathAlreadyExists;
68error SymLinkLoop;
69error ReadOnlyFileSystem;
70error LinkQuotaExceeded;
71error RenameAcrossMountPoints;
72error DirNotEmpty;
73error WouldBlock;
74
7560/// Fills `buf` with random bytes. If linking against libc, this calls the
7661/// appropriate OS-specific library call. Otherwise it uses the zig standard
7762/// library implementation.
78pub fn getRandomBytes(buf: []u8) %void {
63pub fn getRandomBytes(buf: []u8) !void {
7964 switch (builtin.os) {
8065 Os.linux => while (true) {
8166 // TODO check libc version and potentially call c.getrandom.
......@@ -182,7 +167,7 @@ pub fn close(handle: FileHandle) void {
182167}
183168
184169/// Calls POSIX read, and keeps trying if it gets interrupted.
185pub fn posixRead(fd: i32, buf: []u8) %void {
170pub fn posixRead(fd: i32, buf: []u8) !void {
186171 var index: usize = 0;
187172 while (index < buf.len) {
188173 const amt_written = posix.read(fd, &buf[index], buf.len - index);
......@@ -203,17 +188,8 @@ pub fn posixRead(fd: i32, buf: []u8) %void {
203188 }
204189}
205190
206error WouldBlock;
207error FileClosed;
208error DestinationAddressRequired;
209error DiskQuota;
210error FileTooBig;
211error InputOutput;
212error NoSpaceLeft;
213error BrokenPipe;
214
215191/// Calls POSIX write, and keeps trying if it gets interrupted.
216pub fn posixWrite(fd: i32, bytes: []const u8) %void {
192pub fn posixWrite(fd: i32, bytes: []const u8) !void {
217193 while (true) {
218194 const write_ret = posix.write(fd, bytes.ptr, bytes.len);
219195 const write_err = posix.getErrno(write_ret);
......@@ -243,7 +219,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) %void {
243219/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
244220/// Calls POSIX open, keeps trying if it gets interrupted, and translates
245221/// the return value into zig errors.
246pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Allocator) %i32 {
222pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Allocator) !i32 {
247223 var stack_buf: [max_noalloc_path_len]u8 = undefined;
248224 var path0: []u8 = undefined;
249225 var need_free = false;
......@@ -292,7 +268,7 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al
292268 }
293269}
294270
295pub fn posixDup2(old_fd: i32, new_fd: i32) %void {
271pub fn posixDup2(old_fd: i32, new_fd: i32) !void {
296272 while (true) {
297273 const err = posix.getErrno(posix.dup2(old_fd, new_fd));
298274 if (err > 0) {
......@@ -307,7 +283,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) %void {
307283 }
308284}
309285
310pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) %[]?&u8 {
286pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) ![]?&u8 {
311287 const envp_count = env_map.count();
312288 const envp_buf = try allocator.alloc(?&u8, envp_count + 1);
313289 mem.set(?&u8, envp_buf, null);
......@@ -344,7 +320,7 @@ pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void {
344320/// `argv[0]` is the executable path.
345321/// This function also uses the PATH environment variable to get the full path to the executable.
346322pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap,
347 allocator: &Allocator) %void
323 allocator: &Allocator) !void
348324{
349325 const argv_buf = try allocator.alloc(?&u8, argv.len + 1);
350326 mem.set(?&u8, argv_buf, null);
......@@ -419,7 +395,7 @@ fn posixExecveErrnoToErr(err: usize) error {
419395pub var posix_environ_raw: []&u8 = undefined;
420396
421397/// Caller must free result when done.
422pub fn getEnvMap(allocator: &Allocator) %BufMap {
398pub fn getEnvMap(allocator: &Allocator) !BufMap {
423399 var result = BufMap.init(allocator);
424400 errdefer result.deinit();
425401
......@@ -480,10 +456,8 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
480456 return null;
481457}
482458
483error EnvironmentVariableNotFound;
484
485459/// Caller must free returned memory.
486pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) %[]u8 {
460pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) ![]u8 {
487461 if (is_windows) {
488462 const key_with_null = try cstr.addNullByte(allocator, key);
489463 defer allocator.free(key_with_null);
......@@ -517,7 +491,7 @@ pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) %[]u8 {
517491}
518492
519493/// Caller must free the returned memory.
520pub fn getCwd(allocator: &Allocator) %[]u8 {
494pub fn getCwd(allocator: &Allocator) ![]u8 {
521495 switch (builtin.os) {
522496 Os.windows => {
523497 var buf = try allocator.alloc(u8, 256);
......@@ -564,7 +538,7 @@ test "os.getCwd" {
564538 _ = getCwd(debug.global_allocator);
565539}
566540
567pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void {
541pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void {
568542 if (is_windows) {
569543 return symLinkWindows(allocator, existing_path, new_path);
570544 } else {
......@@ -572,7 +546,7 @@ pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []con
572546 }
573547}
574548
575pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void {
549pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void {
576550 const existing_with_null = try cstr.addNullByte(allocator, existing_path);
577551 defer allocator.free(existing_with_null);
578552 const new_with_null = try cstr.addNullByte(allocator, new_path);
......@@ -586,7 +560,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path
586560 }
587561}
588562
589pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void {
563pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void {
590564 const full_buf = try allocator.alloc(u8, existing_path.len + new_path.len + 2);
591565 defer allocator.free(full_buf);
592566
......@@ -623,7 +597,7 @@ const b64_fs_encoder = base64.Base64Encoder.init(
623597 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
624598 base64.standard_pad_char);
625599
626pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void {
600pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void {
627601 if (symLink(allocator, existing_path, new_path)) {
628602 return;
629603 } else |err| {
......@@ -652,7 +626,7 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path:
652626
653627}
654628
655pub fn deleteFile(allocator: &Allocator, file_path: []const u8) %void {
629pub fn deleteFile(allocator: &Allocator, file_path: []const u8) !void {
656630 if (builtin.os == Os.windows) {
657631 return deleteFileWindows(allocator, file_path);
658632 } else {
......@@ -660,10 +634,7 @@ pub fn deleteFile(allocator: &Allocator, file_path: []const u8) %void {
660634 }
661635}
662636
663error FileNotFound;
664error AccessDenied;
665
666pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) %void {
637pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) !void {
667638 const buf = try allocator.alloc(u8, file_path.len + 1);
668639 defer allocator.free(buf);
669640
......@@ -681,7 +652,7 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) %void {
681652 }
682653}
683654
684pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) %void {
655pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) !void {
685656 const buf = try allocator.alloc(u8, file_path.len + 1);
686657 defer allocator.free(buf);
687658
......@@ -708,13 +679,13 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) %void {
708679}
709680
710681/// Calls ::copyFileMode with 0o666 for the mode.
711pub fn copyFile(allocator: &Allocator, source_path: []const u8, dest_path: []const u8) %void {
682pub fn copyFile(allocator: &Allocator, source_path: []const u8, dest_path: []const u8) !void {
712683 return copyFileMode(allocator, source_path, dest_path, 0o666);
713684}
714685
715686// TODO instead of accepting a mode argument, use the mode from fstat'ing the source path once open
716687/// Guaranteed to be atomic.
717pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: []const u8, mode: usize) %void {
688pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: []const u8, mode: usize) !void {
718689 var rand_buf: [12]u8 = undefined;
719690 const tmp_path = try allocator.alloc(u8, dest_path.len + base64.Base64Encoder.calcSize(rand_buf.len));
720691 defer allocator.free(tmp_path);
......@@ -738,7 +709,7 @@ pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: [
738709 }
739710}
740711
741pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) %void {
712pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) !void {
742713 const full_buf = try allocator.alloc(u8, old_path.len + new_path.len + 2);
743714 defer allocator.free(full_buf);
744715
......@@ -783,7 +754,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8)
783754 }
784755}
785756
786pub fn makeDir(allocator: &Allocator, dir_path: []const u8) %void {
757pub fn makeDir(allocator: &Allocator, dir_path: []const u8) !void {
787758 if (is_windows) {
788759 return makeDirWindows(allocator, dir_path);
789760 } else {
......@@ -791,7 +762,7 @@ pub fn makeDir(allocator: &Allocator, dir_path: []const u8) %void {
791762 }
792763}
793764
794pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) %void {
765pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) !void {
795766 const path_buf = try cstr.addNullByte(allocator, dir_path);
796767 defer allocator.free(path_buf);
797768
......@@ -805,7 +776,7 @@ pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) %void {
805776 }
806777}
807778
808pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) %void {
779pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) !void {
809780 const path_buf = try cstr.addNullByte(allocator, dir_path);
810781 defer allocator.free(path_buf);
811782
......@@ -831,7 +802,7 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) %void {
831802
832803/// Calls makeDir recursively to make an entire path. Returns success if the path
833804/// already exists and is a directory.
834pub fn makePath(allocator: &Allocator, full_path: []const u8) %void {
805pub fn makePath(allocator: &Allocator, full_path: []const u8) !void {
835806 const resolved_path = try path.resolve(allocator, full_path);
836807 defer allocator.free(resolved_path);
837808
......@@ -869,7 +840,7 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) %void {
869840
870841/// Returns ::error.DirNotEmpty if the directory is not empty.
871842/// To delete a directory recursively, see ::deleteTree
872pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) %void {
843pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void {
873844 const path_buf = try allocator.alloc(u8, dir_path.len + 1);
874845 defer allocator.free(path_buf);
875846
......@@ -898,7 +869,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) %void {
898869/// removes it. If it cannot be removed because it is a non-empty directory,
899870/// this function recursively removes its entries and then tries again.
900871// TODO non-recursive implementation
901pub fn deleteTree(allocator: &Allocator, full_path: []const u8) %void {
872pub fn deleteTree(allocator: &Allocator, full_path: []const u8) !void {
902873 start_over: while (true) {
903874 // First, try deleting the item as a file. This way we don't follow sym links.
904875 if (deleteFile(allocator, full_path)) {
......@@ -967,7 +938,7 @@ pub const Dir = struct {
967938 };
968939 };
969940
970 pub fn open(allocator: &Allocator, dir_path: []const u8) %Dir {
941 pub fn open(allocator: &Allocator, dir_path: []const u8) !Dir {
971942 const fd = try posixOpen(dir_path, posix.O_RDONLY|posix.O_DIRECTORY|posix.O_CLOEXEC, 0, allocator);
972943 return Dir {
973944 .allocator = allocator,
......@@ -985,7 +956,7 @@ pub const Dir = struct {
985956
986957 /// Memory such as file names referenced in this returned entry becomes invalid
987958 /// with subsequent calls to next, as well as when this ::Dir is deinitialized.
988 pub fn next(self: &Dir) %?Entry {
959 pub fn next(self: &Dir) !?Entry {
989960 start_over: while (true) {
990961 if (self.index >= self.end_index) {
991962 if (self.buf.len == 0) {
......@@ -1042,7 +1013,7 @@ pub const Dir = struct {
10421013 }
10431014};
10441015
1045pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) %void {
1016pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) !void {
10461017 const path_buf = try allocator.alloc(u8, dir_path.len + 1);
10471018 defer allocator.free(path_buf);
10481019
......@@ -1066,7 +1037,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) %void {
10661037}
10671038
10681039/// Read value of a symbolic link.
1069pub fn readLink(allocator: &Allocator, pathname: []const u8) %[]u8 {
1040pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 {
10701041 const path_buf = try allocator.alloc(u8, pathname.len + 1);
10711042 defer allocator.free(path_buf);
10721043
......@@ -1143,11 +1114,7 @@ test "os.sleep" {
11431114 sleep(0, 1);
11441115}
11451116
1146error ResourceLimitReached;
1147error InvalidUserId;
1148error PermissionDenied;
1149
1150pub fn posix_setuid(uid: u32) %void {
1117pub fn posix_setuid(uid: u32) !void {
11511118 const err = posix.getErrno(posix.setuid(uid));
11521119 if (err == 0) return;
11531120 return switch (err) {
......@@ -1158,7 +1125,7 @@ pub fn posix_setuid(uid: u32) %void {
11581125 };
11591126}
11601127
1161pub fn posix_setreuid(ruid: u32, euid: u32) %void {
1128pub fn posix_setreuid(ruid: u32, euid: u32) !void {
11621129 const err = posix.getErrno(posix.setreuid(ruid, euid));
11631130 if (err == 0) return;
11641131 return switch (err) {
......@@ -1169,7 +1136,7 @@ pub fn posix_setreuid(ruid: u32, euid: u32) %void {
11691136 };
11701137}
11711138
1172pub fn posix_setgid(gid: u32) %void {
1139pub fn posix_setgid(gid: u32) !void {
11731140 const err = posix.getErrno(posix.setgid(gid));
11741141 if (err == 0) return;
11751142 return switch (err) {
......@@ -1180,7 +1147,7 @@ pub fn posix_setgid(gid: u32) %void {
11801147 };
11811148}
11821149
1183pub fn posix_setregid(rgid: u32, egid: u32) %void {
1150pub fn posix_setregid(rgid: u32, egid: u32) !void {
11841151 const err = posix.getErrno(posix.setregid(rgid, egid));
11851152 if (err == 0) return;
11861153 return switch (err) {
......@@ -1191,8 +1158,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) %void {
11911158 };
11921159}
11931160
1194error NoStdHandles;
1195pub fn windowsGetStdHandle(handle_id: windows.DWORD) %windows.HANDLE {
1161pub fn windowsGetStdHandle(handle_id: windows.DWORD) !windows.HANDLE {
11961162 if (windows.GetStdHandle(handle_id)) |handle| {
11971163 if (handle == windows.INVALID_HANDLE_VALUE) {
11981164 const err = windows.GetLastError();
......@@ -1261,7 +1227,7 @@ pub const ArgIteratorWindows = struct {
12611227 }
12621228
12631229 /// You must free the returned memory when done.
1264 pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?%[]u8 {
1230 pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?internalNext.errors![]u8 {
12651231 // march forward over whitespace
12661232 while (true) : (self.index += 1) {
12671233 const byte = self.cmd_line[self.index];
......@@ -1314,7 +1280,7 @@ pub const ArgIteratorWindows = struct {
13141280 }
13151281 }
13161282
1317 fn internalNext(self: &ArgIteratorWindows, allocator: &Allocator) %[]u8 {
1283 fn internalNext(self: &ArgIteratorWindows, allocator: &Allocator) ![]u8 {
13181284 var buf = try Buffer.initSize(allocator, 0);
13191285 defer buf.deinit();
13201286
......@@ -1358,7 +1324,7 @@ pub const ArgIteratorWindows = struct {
13581324 }
13591325 }
13601326
1361 fn emitBackslashes(self: &ArgIteratorWindows, buf: &Buffer, emit_count: usize) %void {
1327 fn emitBackslashes(self: &ArgIteratorWindows, buf: &Buffer, emit_count: usize) !void {
13621328 var i: usize = 0;
13631329 while (i < emit_count) : (i += 1) {
13641330 try buf.appendByte('\\');
......@@ -1397,7 +1363,7 @@ pub const ArgIterator = struct {
13971363 }
13981364
13991365 /// You must free the returned memory when done.
1400 pub fn next(self: &ArgIterator, allocator: &Allocator) ?%[]u8 {
1366 pub fn next(self: &ArgIterator, allocator: &Allocator) ?![]u8 {
14011367 if (builtin.os == Os.windows) {
14021368 return self.inner.next(allocator);
14031369 } else {
......@@ -1422,7 +1388,7 @@ pub fn args() ArgIterator {
14221388}
14231389
14241390/// Caller must call freeArgs on result.
1425pub fn argsAlloc(allocator: &mem.Allocator) %[]const []u8 {
1391pub fn argsAlloc(allocator: &mem.Allocator) ![]const []u8 {
14261392 // TODO refactor to only make 1 allocation.
14271393 var it = args();
14281394 var contents = try Buffer.initSize(allocator, 0);
......@@ -1529,7 +1495,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) error {
15291495 return error.Unexpected;
15301496}
15311497
1532pub fn openSelfExe() %io.File {
1498pub fn openSelfExe() !io.File {
15331499 switch (builtin.os) {
15341500 Os.linux => {
15351501 return io.File.openRead("/proc/self/exe", null);
......@@ -1547,7 +1513,7 @@ pub fn openSelfExe() %io.File {
15471513/// This function may return an error if the current executable
15481514/// was deleted after spawning.
15491515/// Caller owns returned memory.
1550pub fn selfExePath(allocator: &mem.Allocator) %[]u8 {
1516pub fn selfExePath(allocator: &mem.Allocator) ![]u8 {
15511517 switch (builtin.os) {
15521518 Os.linux => {
15531519 // If the currently executing binary has been deleted,
......@@ -1590,7 +1556,7 @@ pub fn selfExePath(allocator: &mem.Allocator) %[]u8 {
15901556
15911557/// Get the directory path that contains the current executable.
15921558/// Caller owns returned memory.
1593pub fn selfExeDirPath(allocator: &mem.Allocator) %[]u8 {
1559pub fn selfExeDirPath(allocator: &mem.Allocator) ![]u8 {
15941560 switch (builtin.os) {
15951561 Os.linux => {
15961562 // If the currently executing binary has been deleted,
std/special/test_runner.zig+1-1
......@@ -4,7 +4,7 @@ const builtin = @import("builtin");
44const test_fn_list = builtin.__zig_test_fn_slice;
55const warn = std.debug.warn;
66
7pub fn main() %void {
7pub fn main() !void {
88 for (test_fn_list) |test_fn, i| {
99 warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
1010