diff --git a/src/ir.cpp b/src/ir.cpp index c572e3c885e8c690fce2d85148a8516f9e004680..de4543df4e617fe240d9b1651fb95debe8be6247 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -356,6 +356,28 @@ static void ir_ref_var(ZigVar *var) { var->ref_count += 1; } +ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { + ConstExprValue *result = ir_eval_const_value( ira->codegen + , scope + , node + , ira->codegen->builtin_types.entry_type + , ira->new_irb.exec->backward_branch_count + , ira->new_irb.exec->backward_branch_quota + , nullptr + , nullptr + , node + , nullptr + , ira->new_irb.exec + , nullptr + ); + + if (type_is_invalid(result->type)) + return ira->codegen->builtin_types.entry_invalid; + + assert(result->special != ConstValSpecialRuntime); + return result->data.x_type; +} + static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) { IrBasicBlock *result = allocate(1); result->scope = scope; @@ -13875,7 +13897,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node IrInstruction *casted_arg; if (param_decl_node->data.param_decl.var_token == nullptr) { AstNode *param_type_node = param_decl_node->data.param_decl.type; - ZigType *param_type = analyze_type_expr(ira->codegen, *exec_scope, param_type_node); + ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node); if (type_is_invalid(param_type)) return false; @@ -13915,7 +13937,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod } else { if (param_decl_node->data.param_decl.var_token == nullptr) { AstNode *param_type_node = param_decl_node->data.param_decl.type; - ZigType *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node); + ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node); if (type_is_invalid(param_type)) return false; @@ -14296,7 +14318,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call } AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; - ZigType *specified_return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node); + ZigType *specified_return_type = ir_analyze_type_expr(ira, exec_scope, return_type_node); if (type_is_invalid(specified_return_type)) return ira->codegen->invalid_instruction; ZigType *return_type; @@ -14532,7 +14554,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call if (fn_proto_node->data.fn_proto.return_var_token == nullptr) { AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; - ZigType *specified_return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node); + ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node); if (type_is_invalid(specified_return_type)) return ira->codegen->invalid_instruction; if (fn_proto_node->data.fn_proto.auto_err_set) { @@ -14559,7 +14581,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call if (call_instruction->is_async) { AstNode *async_allocator_type_node = fn_proto_node->data.fn_proto.async_allocator_type; if (async_allocator_type_node != nullptr) { - ZigType *async_allocator_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, async_allocator_type_node); + ZigType *async_allocator_type = ir_analyze_type_expr(ira, impl_fn->child_scope, async_allocator_type_node); if (type_is_invalid(async_allocator_type)) return ira->codegen->invalid_instruction; inst_fn_type_id.async_allocator_type = async_allocator_type; diff --git a/std/hash_map.zig b/std/hash_map.zig index f4c0b87167866e5183eb2d1cbf8992d247f61059..6ea128c9adea4f1a20638181ec25431ef0bc1bba 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -175,7 +175,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 return hm.get(key) != null; } - pub fn remove(hm: *Self, key: K) ?*KV { + pub fn remove(hm: *Self, key: K) ?KV { if (hm.entries.len == 0) return null; hm.incrementModificationCount(); const start_index = hm.keyToIndex(key); @@ -189,13 +189,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 if (!eql(entry.kv.key, key)) continue; + const removed_kv = entry.kv; while (roll_over < hm.entries.len) : (roll_over += 1) { const next_index = (start_index + roll_over + 1) % hm.entries.len; const next_entry = &hm.entries[next_index]; if (!next_entry.used or next_entry.distance_from_start_index == 0) { entry.used = false; hm.size -= 1; - return &entry.kv; + return removed_kv; } entry.* = next_entry.*; entry.distance_from_start_index -= 1; @@ -371,7 +372,10 @@ test "basic hash map usage" { testing.expect(map.contains(2)); testing.expect(map.get(2).?.value == 22); - _ = map.remove(2); + + const rmv1 = map.remove(2); + testing.expect(rmv1.?.key == 2); + testing.expect(rmv1.?.value == 22); testing.expect(map.remove(2) == null); testing.expect(map.get(2) == null); } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index a31605b02abc9cd99a5c96261bfefcc3f924c0f8..0d30bd71750c7d7c9d5af7c845c811b07c8198a6 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,21 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "Generic function where return type is self-referenced", + \\fn Foo(comptime T: type) Foo(T) { + \\ return struct{ x: T }; + \\} + \\export fn entry() void { + \\ const t = Foo(u32) { + \\ .x = 1 + \\ }; + \\} + , + "tmp.zig:1:29: error: evaluation exceeded 1000 backwards branches", + "tmp.zig:1:29: note: called from here", + ); + cases.add( "@ptrToInt 0 to non optional pointer", \\export fn entry() void {