authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-28 11:17:20-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-28 11:17:20-04:00
log7139eef4cfc7c75655f9951849a994b116e96abe
treeda10043f4783052423a2b394309d523a0f6840eb
parentac477f3c9a94b6d32a56d89a01ae24c68143ee5d
signaturelock-open Commit is signed but in an unrecognized format.

implement lazy values for error union types

closes #3129

4 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};
316317
317struct LazyValue {318struct LazyValue {
...@@ -372,6 +373,14 @@ struct LazyValueFnType {...@@ -372,6 +373,14 @@ struct LazyValueFnType {
372 bool is_generic;373 bool is_generic;
373};374};
374375
376struct LazyValueErrUnionType {
377 LazyValue base;
378
379 IrAnalyze *ira;
380 IrInstruction *err_set_type;
381 IrInstruction *payload_type;
382};
383
375struct ConstExprValue {384struct 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)))1113start_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,
14626static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira,14626static 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;
1463014631
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;
1463414636
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;
1463814640
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 }
1464514644
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}
1465214647
14653static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type,14648static 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(); TODO376 //comptime S.entry(); TODO
377}377}
378
379test "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}