| 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 | 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 | 4679 | while (scope) { |
| 4636 | 4680 | if (scope->id == ScopeIdVarDecl) { |
| 4637 | 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 | 196 | uint32_t get_coro_frame_align_bytes(CodeGen *g); |
| 197 | 197 | bool fn_type_can_fail(FnTypeId *fn_type_id); |
| 198 | 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 | 201 | #endif |
src/ir.cpp+1-1| ... | ... | @@ -11878,7 +11878,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 11878 | 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 | 11882 | IrInstruction *result = nullptr; |
| 11883 | 11883 | if (cacheable) { |
| 11884 | 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 | 369 | |
| 370 | 370 | |
| 371 | 371 | test "base64" { |
| 372 | @setEvalBranchQuota(5000); | |
| 372 | @setEvalBranchQuota(8000); | |
| 373 | 373 | testBase64() catch unreachable; |
| 374 | 374 | comptime (testBase64() catch unreachable); |
| 375 | 375 | } |
test/behavior.zig+1| ... | ... | @@ -11,6 +11,7 @@ comptime { |
| 11 | 11 | _ = @import("cases/bugs/394.zig"); |
| 12 | 12 | _ = @import("cases/bugs/655.zig"); |
| 13 | 13 | _ = @import("cases/bugs/656.zig"); |
| 14 | _ = @import("cases/bugs/828.zig"); | |
| 14 | 15 | _ = @import("cases/cast.zig"); |
| 15 | 16 | _ = @import("cases/const_slice_child.zig"); |
| 16 | 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 | } |