| author | |
| committer | |
| log | bcce77700fe0967b4dd796a3a21605868b6f9aa2 |
| tree | b3a062d4a1e3ed2e2cf103af89510670a783dd87 |
| parent | 5834ff0cc58ffba8e4fe218fcf888d9f9fcf95b2 |
closes #8286 files changed, 86 insertions(+), 4 deletions(-)
src/analyze.cpp+45-1| ... | @@ -4631,7 +4631,51 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { | ... | @@ -4631,7 +4631,51 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| 4631 | zig_unreachable(); | 4631 | zig_unreachable(); |
| 4632 | } | 4632 | } |
| 4633 | 4633 | ||
| 4634 | bool fn_eval_cacheable(Scope *scope) { | 4634 | static bool return_type_is_cacheable(TypeTableEntry *return_type) { |
| 4635 | switch (return_type->id) { | ||
| 4636 | case TypeTableEntryIdInvalid: | ||
| 4637 | zig_unreachable(); | ||
| 4638 | case TypeTableEntryIdMetaType: | ||
| 4639 | case TypeTableEntryIdVoid: | ||
| 4640 | case TypeTableEntryIdBool: | ||
| 4641 | case TypeTableEntryIdUnreachable: | ||
| 4642 | case TypeTableEntryIdInt: | ||
| 4643 | case TypeTableEntryIdFloat: | ||
| 4644 | case TypeTableEntryIdNumLitFloat: | ||
| 4645 | case TypeTableEntryIdNumLitInt: | ||
| 4646 | case TypeTableEntryIdUndefLit: | ||
| 4647 | case TypeTableEntryIdNullLit: | ||
| 4648 | case TypeTableEntryIdNamespace: | ||
| 4649 | case TypeTableEntryIdBoundFn: | ||
| 4650 | case TypeTableEntryIdFn: | ||
| 4651 | case TypeTableEntryIdBlock: | ||
| 4652 | case TypeTableEntryIdOpaque: | ||
| 4653 | case TypeTableEntryIdPromise: | ||
| 4654 | case TypeTableEntryIdErrorSet: | ||
| 4655 | case TypeTableEntryIdEnum: | ||
| 4656 | case TypeTableEntryIdPointer: | ||
| 4657 | return true; | ||
| 4658 | |||
| 4659 | case TypeTableEntryIdArray: | ||
| 4660 | case TypeTableEntryIdStruct: | ||
| 4661 | case TypeTableEntryIdUnion: | ||
| 4662 | return false; | ||
| 4663 | |||
| 4664 | case TypeTableEntryIdMaybe: | ||
| 4665 | return return_type_is_cacheable(return_type->data.maybe.child_type); | ||
| 4666 | |||
| 4667 | case TypeTableEntryIdErrorUnion: | ||
| 4668 | return return_type_is_cacheable(return_type->data.error_union.payload_type); | ||
| 4669 | |||
| 4670 | case TypeTableEntryIdArgTuple: | ||
| 4671 | zig_panic("TODO var args at comptime is currently not supported"); | ||
| 4672 | } | ||
| 4673 | zig_unreachable(); | ||
| 4674 | } | ||
| 4675 | |||
| 4676 | bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type) { | ||
| 4677 | if (!return_type_is_cacheable(return_type)) | ||
| 4678 | return false; | ||
| 4635 | while (scope) { | 4679 | while (scope) { |
| 4636 | if (scope->id == ScopeIdVarDecl) { | 4680 | if (scope->id == ScopeIdVarDecl) { |
| 4637 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; | 4681 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; |
src/analyze.hpp+1-1| ... | @@ -196,6 +196,6 @@ TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry); | ... | @@ -196,6 +196,6 @@ TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry); |
| 196 | uint32_t get_coro_frame_align_bytes(CodeGen *g); | 196 | uint32_t get_coro_frame_align_bytes(CodeGen *g); |
| 197 | bool fn_type_can_fail(FnTypeId *fn_type_id); | 197 | bool fn_type_can_fail(FnTypeId *fn_type_id); |
| 198 | bool type_can_fail(TypeTableEntry *type_entry); | 198 | bool type_can_fail(TypeTableEntry *type_entry); |
| 199 | bool fn_eval_cacheable(Scope *scope); | 199 | bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type); |
| 200 | 200 | ||
| 201 | #endif | 201 | #endif |
src/ir.cpp+1-1| ... | @@ -11878,7 +11878,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -11878,7 +11878,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 11878 | return_type = specified_return_type; | 11878 | return_type = specified_return_type; |
| 11879 | } | 11879 | } |
| 11880 | 11880 | ||
| 11881 | bool cacheable = fn_eval_cacheable(exec_scope); | 11881 | bool cacheable = fn_eval_cacheable(exec_scope, return_type); |
| 11882 | IrInstruction *result = nullptr; | 11882 | IrInstruction *result = nullptr; |
| 11883 | if (cacheable) { | 11883 | if (cacheable) { |
| 11884 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); | 11884 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); |
std/base64.zig+1-1| ... | @@ -369,7 +369,7 @@ fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) usize { | ... | @@ -369,7 +369,7 @@ fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) usize { |
| 369 | 369 | ||
| 370 | 370 | ||
| 371 | test "base64" { | 371 | test "base64" { |
| 372 | @setEvalBranchQuota(5000); | 372 | @setEvalBranchQuota(8000); |
| 373 | testBase64() catch unreachable; | 373 | testBase64() catch unreachable; |
| 374 | comptime (testBase64() catch unreachable); | 374 | comptime (testBase64() catch unreachable); |
| 375 | } | 375 | } |
test/behavior.zig+1| ... | @@ -11,6 +11,7 @@ comptime { | ... | @@ -11,6 +11,7 @@ comptime { |
| 11 | _ = @import("cases/bugs/394.zig"); | 11 | _ = @import("cases/bugs/394.zig"); |
| 12 | _ = @import("cases/bugs/655.zig"); | 12 | _ = @import("cases/bugs/655.zig"); |
| 13 | _ = @import("cases/bugs/656.zig"); | 13 | _ = @import("cases/bugs/656.zig"); |
| 14 | _ = @import("cases/bugs/828.zig"); | ||
| 14 | _ = @import("cases/cast.zig"); | 15 | _ = @import("cases/cast.zig"); |
| 15 | _ = @import("cases/const_slice_child.zig"); | 16 | _ = @import("cases/const_slice_child.zig"); |
| 16 | _ = @import("cases/coroutines.zig"); | 17 | _ = @import("cases/coroutines.zig"); |
test/cases/bugs/828.zig created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | const CountBy = struct { | ||
| 2 | a: usize, | ||
| 3 | |||
| 4 | const One = CountBy { | ||
| 5 | .a = 1, | ||
| 6 | }; | ||
| 7 | |||
| 8 | pub fn counter(self: &const CountBy) Counter { | ||
| 9 | return Counter { | ||
| 10 | .i = 0, | ||
| 11 | }; | ||
| 12 | } | ||
| 13 | }; | ||
| 14 | |||
| 15 | const Counter = struct { | ||
| 16 | i: usize, | ||
| 17 | |||
| 18 | pub fn count(self: &Counter) bool { | ||
| 19 | self.i += 1; | ||
| 20 | return self.i <= 10; | ||
| 21 | } | ||
| 22 | }; | ||
| 23 | |||
| 24 | fn constCount(comptime cb: &const CountBy, comptime unused: u32) void { | ||
| 25 | comptime { | ||
| 26 | var cnt = cb.counter(); | ||
| 27 | if(cnt.i != 0) @compileError("Counter instance reused!"); | ||
| 28 | while(cnt.count()){} | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | test "comptime struct return should not return the same instance" { | ||
| 33 | //the first parameter must be passed by reference to trigger the bug | ||
| 34 | //a second parameter is required to trigger the bug | ||
| 35 | const ValA = constCount(&CountBy.One, 12); | ||
| 36 | const ValB = constCount(&CountBy.One, 15); | ||
| 37 | } | ||