Commit 9983501ff2
Changed files (3)
src
test
stage1
behavior
src/ir.cpp
@@ -17675,18 +17675,36 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
assert(container_scope != nullptr);
auto entry = container_scope->decl_table.maybe_get(field_name);
Tld *tld = entry ? entry->value : nullptr;
- if (tld && tld->id == TldIdFn) {
- resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
- if (tld->resolution == TldResolutionInvalid)
- return ira->codegen->invalid_instruction;
- TldFn *tld_fn = (TldFn *)tld;
- ZigFn *fn_entry = tld_fn->fn_entry;
- if (type_is_invalid(fn_entry->type_entry))
- return ira->codegen->invalid_instruction;
+ if (tld) {
+ if (tld->id == TldIdFn) {
+ resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
+ if (tld->resolution == TldResolutionInvalid)
+ return ira->codegen->invalid_instruction;
+ TldFn *tld_fn = (TldFn *)tld;
+ ZigFn *fn_entry = tld_fn->fn_entry;
+ if (type_is_invalid(fn_entry->type_entry))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, fn_entry, container_ptr);
+ return ir_get_ref(ira, source_instr, bound_fn_value, true, false);
+ } else if (tld->id == TldIdVar) {
+ resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
+ if (tld->resolution == TldResolutionInvalid)
+ return ira->codegen->invalid_instruction;
+ TldVar *tld_var = (TldVar *)tld;
+ ZigVar *var = tld_var->var;
+ if (type_is_invalid(var->var_type))
+ return ira->codegen->invalid_instruction;
- IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope,
- source_instr->source_node, fn_entry, container_ptr);
- return ir_get_ref(ira, source_instr, bound_fn_value, true, false);
+ if (var->const_value->type->id == ZigTypeIdFn) {
+ ir_assert(var->const_value->data.x_ptr.special == ConstPtrSpecialFunction, source_instr);
+ ZigFn *fn = var->const_value->data.x_ptr.data.fn.fn_entry;
+ IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, fn, container_ptr);
+ return ir_get_ref(ira, source_instr, bound_fn_value, true, false);
+ }
+ }
}
}
const char *prefix_name;
test/stage1/behavior/fn_delegation.zig
@@ -0,0 +1,39 @@
+const expect = @import("std").testing.expect;
+
+const Foo = struct {
+ a: u64 = 10,
+
+ fn one(self: Foo) u64 {
+ return self.a + 1;
+ }
+
+ const two = __two;
+
+ fn __two(self: Foo) u64 {
+ return self.a + 2;
+ }
+
+ const three = __three;
+
+ const four = custom(Foo, 4);
+};
+
+fn __three(self: Foo) u64 {
+ return self.a + 3;
+}
+
+fn custom(comptime T: type, comptime num: u64) fn (T) u64 {
+ return struct {
+ fn function(self: T) u64 {
+ return self.a + num;
+ }
+ }.function;
+}
+
+test "fn delegation" {
+ const foo = Foo{};
+ expect(foo.one() == 11);
+ expect(foo.two() == 12);
+ expect(foo.three() == 13);
+ expect(foo.four() == 14);
+}
test/stage1/behavior.zig
@@ -58,6 +58,7 @@ comptime {
_ = @import("behavior/floatop.zig");
_ = @import("behavior/fn.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
+ _ = @import("behavior/fn_delegation.zig");
_ = @import("behavior/for.zig");
_ = @import("behavior/generics.zig");
_ = @import("behavior/hasdecl.zig");