| 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,6 +312,7 @@ enum LazyValueId { |
| 312 | LazyValueIdOptType, | 312 | LazyValueIdOptType, |
| 313 | LazyValueIdSliceType, | 313 | LazyValueIdSliceType, |
| 314 | LazyValueIdFnType, | 314 | LazyValueIdFnType, |
| 315 | LazyValueIdErrUnionType, | ||
| 315 | }; | 316 | }; |
| 316 | 317 | ||
| 317 | struct LazyValue { | 318 | struct LazyValue { |
| ... | @@ -372,6 +373,14 @@ struct LazyValueFnType { | ... | @@ -372,6 +373,14 @@ struct LazyValueFnType { |
| 372 | bool is_generic; | 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 | struct ConstExprValue { | 384 | struct ConstExprValue { |
| 376 | ZigType *type; | 385 | ZigType *type; |
| 377 | ConstValSpecial special; | 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,6 +1015,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi |
| 1015 | } | 1015 | } |
| 1016 | case LazyValueIdOptType: | 1016 | case LazyValueIdOptType: |
| 1017 | case LazyValueIdSliceType: | 1017 | case LazyValueIdSliceType: |
| 1018 | case LazyValueIdErrUnionType: | ||
| 1018 | *is_zero_bits = false; | 1019 | *is_zero_bits = false; |
| 1019 | return ErrorNone; | 1020 | return ErrorNone; |
| 1020 | case LazyValueIdFnType: { | 1021 | case LazyValueIdFnType: { |
| ... | @@ -1040,6 +1041,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool | ... | @@ -1040,6 +1041,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool |
| 1040 | case LazyValueIdPtrType: | 1041 | case LazyValueIdPtrType: |
| 1041 | case LazyValueIdFnType: | 1042 | case LazyValueIdFnType: |
| 1042 | case LazyValueIdOptType: | 1043 | case LazyValueIdOptType: |
| 1044 | case LazyValueIdErrUnionType: | ||
| 1043 | *is_opaque_type = false; | 1045 | *is_opaque_type = false; |
| 1044 | return ErrorNone; | 1046 | return ErrorNone; |
| 1045 | } | 1047 | } |
| ... | @@ -1094,6 +1096,11 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue | ... | @@ -1094,6 +1096,11 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue |
| 1094 | } | 1096 | } |
| 1095 | return ReqCompTimeNo; | 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 | zig_unreachable(); | 1105 | zig_unreachable(); |
| 1099 | } | 1106 | } |
| ... | @@ -1102,10 +1109,8 @@ static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstEx | ... | @@ -1102,10 +1109,8 @@ static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstEx |
| 1102 | size_t *abi_size, size_t *size_in_bits) | 1109 | size_t *abi_size, size_t *size_in_bits) |
| 1103 | { | 1110 | { |
| 1104 | Error err; | 1111 | Error err; |
| 1105 | if (type_val->data.x_lazy->id == LazyValueIdOptType) { | 1112 | |
| 1106 | if ((err = ir_resolve_lazy(g, source_node, type_val))) | 1113 | start_over: |
| 1107 | return err; | ||
| 1108 | } | ||
| 1109 | if (type_val->special != ConstValSpecialLazy) { | 1114 | if (type_val->special != ConstValSpecialLazy) { |
| 1110 | assert(type_val->special == ConstValSpecialStatic); | 1115 | assert(type_val->special == ConstValSpecialStatic); |
| 1111 | ZigType *ty = type_val->data.x_type; | 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,7 +1134,10 @@ static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstEx |
| 1129 | *size_in_bits = g->builtin_types.entry_usize->size_in_bits; | 1134 | *size_in_bits = g->builtin_types.entry_usize->size_in_bits; |
| 1130 | return ErrorNone; | 1135 | return ErrorNone; |
| 1131 | case LazyValueIdOptType: | 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 | zig_unreachable(); | 1142 | zig_unreachable(); |
| 1135 | } | 1143 | } |
| ... | @@ -1161,6 +1169,19 @@ Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t | ... | @@ -1161,6 +1169,19 @@ Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t |
| 1161 | LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy); | 1169 | LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy); |
| 1162 | return type_val_resolve_abi_align(g, &lazy_opt_type->payload_type->value, abi_align); | 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 | zig_unreachable(); | 1186 | zig_unreachable(); |
| 1166 | } | 1187 | } |
| ... | @@ -1189,6 +1210,18 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons | ... | @@ -1189,6 +1210,18 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons |
| 1189 | return OnePossibleValueNo; | 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 | zig_unreachable(); | 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,28 +14626,23 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| 14626 | static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira, | 14626 | static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira, |
| 14627 | IrInstructionErrorUnion *instruction) | 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 | LazyValueErrUnionType *lazy_err_union_type = allocate<LazyValueErrUnionType>(1); |
| 14632 | if (type_is_invalid(err_set_type)) | 14633 | lazy_err_union_type->ira = ira; |
| 14633 | return ira->codegen->invalid_instruction; | 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); | 14637 | lazy_err_union_type->err_set_type = instruction->err_set->child; |
| 14636 | if (type_is_invalid(payload_type)) | 14638 | if (ir_resolve_type_lazy(ira, lazy_err_union_type->err_set_type) == nullptr) |
| 14637 | return ira->codegen->invalid_instruction; | 14639 | return ira->codegen->invalid_instruction; |
| 14638 | 14640 | ||
| 14639 | if (err_set_type->id != ZigTypeIdErrorSet) { | 14641 | lazy_err_union_type->payload_type = instruction->payload->child; |
| 14640 | ir_add_error(ira, instruction->err_set->child, | 14642 | if (ir_resolve_type_lazy(ira, lazy_err_union_type->payload_type) == nullptr) |
| 14641 | buf_sprintf("expected error set type, found type '%s'", | ||
| 14642 | buf_ptr(&err_set_type->name))); | ||
| 14643 | return ira->codegen->invalid_instruction; | 14643 | return ira->codegen->invalid_instruction; |
| 14644 | } | ||
| 14645 | 14644 | ||
| 14646 | if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown))) | 14645 | return result; |
| 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); | ||
| 14651 | } | 14646 | } |
| 14652 | 14647 | ||
| 14653 | static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type, | 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,6 +25693,34 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) { |
| 25698 | val->data.x_type = fn_type; | 25693 | val->data.x_type = fn_type; |
| 25699 | return ErrorNone; | 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 | zig_unreachable(); | 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,3 +375,23 @@ test "implicit cast to optional to error union to return result loc" { |
| 375 | S.entry(); | 375 | S.entry(); |
| 376 | //comptime S.entry(); TODO | 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 | } |