| author | |
| committer | |
| log | 7139eef4cfc7c75655f9951849a994b116e96abe |
| tree | da10043f4783052423a2b394309d523a0f6840eb |
| parent | ac477f3c9a94b6d32a56d89a01ae24c68143ee5d |
| signature |
closes #31294 files changed, 106 insertions(+), 21 deletions(-)
src/all_types.hpp+9| ... | ... | @@ -312,6 +312,7 @@ enum LazyValueId { |
| 312 | 312 | LazyValueIdOptType, |
| 313 | 313 | LazyValueIdSliceType, |
| 314 | 314 | LazyValueIdFnType, |
| 315 | LazyValueIdErrUnionType, | |
| 315 | 316 | }; |
| 316 | 317 | |
| 317 | 318 | struct LazyValue { |
| ... | ... | @@ -372,6 +373,14 @@ struct LazyValueFnType { |
| 372 | 373 | bool is_generic; |
| 373 | 374 | }; |
| 374 | 375 | |
| 376 | struct LazyValueErrUnionType { | |
| 377 | LazyValue base; | |
| 378 | ||
| 379 | IrAnalyze *ira; | |
| 380 | IrInstruction *err_set_type; | |
| 381 | IrInstruction *payload_type; | |
| 382 | }; | |
| 383 | ||
| 375 | 384 | struct ConstExprValue { |
| 376 | 385 | ZigType *type; |
| 377 | 386 | ConstValSpecial special; |
src/analyze.cpp+38-5| ... | ... | @@ -1015,6 +1015,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi |
| 1015 | 1015 | } |
| 1016 | 1016 | case LazyValueIdOptType: |
| 1017 | 1017 | case LazyValueIdSliceType: |
| 1018 | case LazyValueIdErrUnionType: | |
| 1018 | 1019 | *is_zero_bits = false; |
| 1019 | 1020 | return ErrorNone; |
| 1020 | 1021 | case LazyValueIdFnType: { |
| ... | ... | @@ -1040,6 +1041,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool |
| 1040 | 1041 | case LazyValueIdPtrType: |
| 1041 | 1042 | case LazyValueIdFnType: |
| 1042 | 1043 | case LazyValueIdOptType: |
| 1044 | case LazyValueIdErrUnionType: | |
| 1043 | 1045 | *is_opaque_type = false; |
| 1044 | 1046 | return ErrorNone; |
| 1045 | 1047 | } |
| ... | ... | @@ -1094,6 +1096,11 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue |
| 1094 | 1096 | } |
| 1095 | 1097 | return ReqCompTimeNo; |
| 1096 | 1098 | } |
| 1099 | case LazyValueIdErrUnionType: { | |
| 1100 | LazyValueErrUnionType *lazy_err_union_type = | |
| 1101 | reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy); | |
| 1102 | return type_val_resolve_requires_comptime(g, &lazy_err_union_type->payload_type->value); | |
| 1103 | } | |
| 1097 | 1104 | } |
| 1098 | 1105 | zig_unreachable(); |
| 1099 | 1106 | } |
| ... | ... | @@ -1102,10 +1109,8 @@ static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstEx |
| 1102 | 1109 | size_t *abi_size, size_t *size_in_bits) |
| 1103 | 1110 | { |
| 1104 | 1111 | Error err; |
| 1105 | if (type_val->data.x_lazy->id == LazyValueIdOptType) { | |
| 1106 | if ((err = ir_resolve_lazy(g, source_node, type_val))) | |
| 1107 | return err; | |
| 1108 | } | |
| 1112 | ||
| 1113 | start_over: | |
| 1109 | 1114 | if (type_val->special != ConstValSpecialLazy) { |
| 1110 | 1115 | assert(type_val->special == ConstValSpecialStatic); |
| 1111 | 1116 | ZigType *ty = type_val->data.x_type; |
| ... | ... | @@ -1129,7 +1134,10 @@ static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstEx |
| 1129 | 1134 | *size_in_bits = g->builtin_types.entry_usize->size_in_bits; |
| 1130 | 1135 | return ErrorNone; |
| 1131 | 1136 | case LazyValueIdOptType: |
| 1132 | zig_unreachable(); | |
| 1137 | case LazyValueIdErrUnionType: | |
| 1138 | if ((err = ir_resolve_lazy(g, source_node, type_val))) | |
| 1139 | return err; | |
| 1140 | goto start_over; | |
| 1133 | 1141 | } |
| 1134 | 1142 | zig_unreachable(); |
| 1135 | 1143 | } |
| ... | ... | @@ -1161,6 +1169,19 @@ Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t |
| 1161 | 1169 | LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy); |
| 1162 | 1170 | return type_val_resolve_abi_align(g, &lazy_opt_type->payload_type->value, abi_align); |
| 1163 | 1171 | } |
| 1172 | case LazyValueIdErrUnionType: { | |
| 1173 | LazyValueErrUnionType *lazy_err_union_type = | |
| 1174 | reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy); | |
| 1175 | uint32_t payload_abi_align; | |
| 1176 | if ((err = type_val_resolve_abi_align(g, &lazy_err_union_type->payload_type->value, | |
| 1177 | &payload_abi_align))) | |
| 1178 | { | |
| 1179 | return err; | |
| 1180 | } | |
| 1181 | *abi_align = (payload_abi_align > g->err_tag_type->abi_align) ? | |
| 1182 | payload_abi_align : g->err_tag_type->abi_align; | |
| 1183 | return ErrorNone; | |
| 1184 | } | |
| 1164 | 1185 | } |
| 1165 | 1186 | zig_unreachable(); |
| 1166 | 1187 | } |
| ... | ... | @@ -1189,6 +1210,18 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons |
| 1189 | 1210 | return OnePossibleValueNo; |
| 1190 | 1211 | } |
| 1191 | 1212 | } |
| 1213 | case LazyValueIdErrUnionType: { | |
| 1214 | LazyValueErrUnionType *lazy_err_union_type = | |
| 1215 | reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy); | |
| 1216 | switch (type_val_resolve_has_one_possible_value(g, &lazy_err_union_type->err_set_type->value)) { | |
| 1217 | case OnePossibleValueInvalid: | |
| 1218 | return OnePossibleValueInvalid; | |
| 1219 | case OnePossibleValueNo: | |
| 1220 | return OnePossibleValueNo; | |
| 1221 | case OnePossibleValueYes: | |
| 1222 | return type_val_resolve_has_one_possible_value(g, &lazy_err_union_type->payload_type->value); | |
| 1223 | } | |
| 1224 | } | |
| 1192 | 1225 | } |
| 1193 | 1226 | zig_unreachable(); |
| 1194 | 1227 | } |
src/ir.cpp+39-16| ... | ... | @@ -14626,28 +14626,23 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| 14626 | 14626 | static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira, |
| 14627 | 14627 | IrInstructionErrorUnion *instruction) |
| 14628 | 14628 | { |
| 14629 | Error err; | |
| 14629 | IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); | |
| 14630 | result->value.special = ConstValSpecialLazy; | |
| 14630 | 14631 | |
| 14631 | ZigType *err_set_type = ir_resolve_type(ira, instruction->err_set->child); | |
| 14632 | if (type_is_invalid(err_set_type)) | |
| 14633 | return ira->codegen->invalid_instruction; | |
| 14632 | LazyValueErrUnionType *lazy_err_union_type = allocate<LazyValueErrUnionType>(1); | |
| 14633 | lazy_err_union_type->ira = ira; | |
| 14634 | result->value.data.x_lazy = &lazy_err_union_type->base; | |
| 14635 | lazy_err_union_type->base.id = LazyValueIdErrUnionType; | |
| 14634 | 14636 | |
| 14635 | ZigType *payload_type = ir_resolve_type(ira, instruction->payload->child); | |
| 14636 | if (type_is_invalid(payload_type)) | |
| 14637 | lazy_err_union_type->err_set_type = instruction->err_set->child; | |
| 14638 | if (ir_resolve_type_lazy(ira, lazy_err_union_type->err_set_type) == nullptr) | |
| 14637 | 14639 | return ira->codegen->invalid_instruction; |
| 14638 | 14640 | |
| 14639 | if (err_set_type->id != ZigTypeIdErrorSet) { | |
| 14640 | ir_add_error(ira, instruction->err_set->child, | |
| 14641 | buf_sprintf("expected error set type, found type '%s'", | |
| 14642 | buf_ptr(&err_set_type->name))); | |
| 14641 | lazy_err_union_type->payload_type = instruction->payload->child; | |
| 14642 | if (ir_resolve_type_lazy(ira, lazy_err_union_type->payload_type) == nullptr) | |
| 14643 | 14643 | return ira->codegen->invalid_instruction; |
| 14644 | } | |
| 14645 | 14644 | |
| 14646 | if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown))) | |
| 14647 | return ira->codegen->invalid_instruction; | |
| 14648 | ZigType *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type); | |
| 14649 | ||
| 14650 | return ir_const_type(ira, &instruction->base, result_type); | |
| 14645 | return result; | |
| 14651 | 14646 | } |
| 14652 | 14647 | |
| 14653 | 14648 | static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type, |
| ... | ... | @@ -25698,6 +25693,34 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) { |
| 25698 | 25693 | val->data.x_type = fn_type; |
| 25699 | 25694 | return ErrorNone; |
| 25700 | 25695 | } |
| 25696 | case LazyValueIdErrUnionType: { | |
| 25697 | LazyValueErrUnionType *lazy_err_union_type = | |
| 25698 | reinterpret_cast<LazyValueErrUnionType *>(val->data.x_lazy); | |
| 25699 | IrAnalyze *ira = lazy_err_union_type->ira; | |
| 25700 | ||
| 25701 | ZigType *err_set_type = ir_resolve_type(ira, lazy_err_union_type->err_set_type); | |
| 25702 | if (type_is_invalid(err_set_type)) | |
| 25703 | return ErrorSemanticAnalyzeFail; | |
| 25704 | ||
| 25705 | ZigType *payload_type = ir_resolve_type(ira, lazy_err_union_type->payload_type); | |
| 25706 | if (type_is_invalid(payload_type)) | |
| 25707 | return ErrorSemanticAnalyzeFail; | |
| 25708 | ||
| 25709 | if (err_set_type->id != ZigTypeIdErrorSet) { | |
| 25710 | ir_add_error(ira, lazy_err_union_type->err_set_type, | |
| 25711 | buf_sprintf("expected error set type, found type '%s'", | |
| 25712 | buf_ptr(&err_set_type->name))); | |
| 25713 | return ErrorSemanticAnalyzeFail; | |
| 25714 | } | |
| 25715 | ||
| 25716 | if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown))) | |
| 25717 | return ErrorSemanticAnalyzeFail; | |
| 25718 | ||
| 25719 | assert(val->type->id == ZigTypeIdMetaType); | |
| 25720 | val->data.x_type = get_error_union_type(ira->codegen, err_set_type, payload_type); | |
| 25721 | val->special = ConstValSpecialStatic; | |
| 25722 | return ErrorNone; | |
| 25723 | } | |
| 25701 | 25724 | } |
| 25702 | 25725 | zig_unreachable(); |
| 25703 | 25726 | } |
test/stage1/behavior/error.zig+20| ... | ... | @@ -375,3 +375,23 @@ test "implicit cast to optional to error union to return result loc" { |
| 375 | 375 | S.entry(); |
| 376 | 376 | //comptime S.entry(); TODO |
| 377 | 377 | } |
| 378 | ||
| 379 | test "function pointer with return type that is error union with payload which is pointer of parent struct" { | |
| 380 | const S = struct { | |
| 381 | const Foo = struct { | |
| 382 | fun: fn (a: i32) (anyerror!*Foo), | |
| 383 | }; | |
| 384 | ||
| 385 | const Err = error{UnspecifiedErr}; | |
| 386 | ||
| 387 | fn bar(a: i32) anyerror!*Foo { | |
| 388 | return Err.UnspecifiedErr; | |
| 389 | } | |
| 390 | ||
| 391 | fn doTheTest() void { | |
| 392 | var x = Foo{ .fun = bar }; | |
| 393 | expectError(error.UnspecifiedErr, x.fun(1)); | |
| 394 | } | |
| 395 | }; | |
| 396 | S.doTheTest(); | |
| 397 | } |