authorgravatar for ian@ianjohnson.devIan Johnson <ian@ianjohnson.dev> 2023-04-22 20:44:57-04:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-04-24 09:35:54+03:00
log2be347a2c88e435079333773fc30b8e967cc7068
tree6cc383bfa7dff357fcbcb0085f76f46b070ac999
parentc75e11bf6aa67f2ca62b9b6677d134592777bfec

Sema: allow method calls on optional pointers


2 files changed, 40 insertions(+), 12 deletions(-)

src/Sema.zig+23-12
...@@ -23738,7 +23738,6 @@ fn fieldCallBind(...@@ -23738,7 +23738,6 @@ fn fieldCallBind(
23738 {23738 {
23739 const first_param_type = decl_type.fnParamType(0);23739 const first_param_type = decl_type.fnParamType(0);
23740 const first_param_tag = first_param_type.tag();23740 const first_param_tag = first_param_type.tag();
23741 var opt_buf: Type.Payload.ElemType = undefined;
23742 // zig fmt: off23741 // zig fmt: off
23743 if (first_param_tag == .var_args_param or23742 if (first_param_tag == .var_args_param or
23744 first_param_tag == .generic_poison or (23743 first_param_tag == .generic_poison or (
...@@ -23764,17 +23763,29 @@ fn fieldCallBind(...@@ -23764,17 +23763,29 @@ fn fieldCallBind(
23764 .arg0_inst = deref,23763 .arg0_inst = deref,
23765 });23764 });
23766 return sema.addConstant(ty, value);23765 return sema.addConstant(ty, value);
23767 } else if (first_param_tag != .generic_poison and first_param_type.zigTypeTag() == .Optional and23766 } else if (first_param_type.zigTypeTag() == .Optional) {
23768 first_param_type.optionalChild(&opt_buf).eql(concrete_ty, sema.mod))23767 var opt_buf: Type.Payload.ElemType = undefined;
23769 {23768 const child = first_param_type.optionalChild(&opt_buf);
23770 const deref = try sema.analyzeLoad(block, src, object_ptr, src);23769 if (child.eql(concrete_ty, sema.mod)) {
23771 const ty = Type.Tag.bound_fn.init();23770 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
23772 const value = try Value.Tag.bound_fn.create(arena, .{23771 const ty = Type.Tag.bound_fn.init();
23773 .func_inst = decl_val,23772 const value = try Value.Tag.bound_fn.create(arena, .{
23774 .arg0_inst = deref,23773 .func_inst = decl_val,
23775 });23774 .arg0_inst = deref,
23776 return sema.addConstant(ty, value);23775 });
23777 } else if (first_param_tag != .generic_poison and first_param_type.zigTypeTag() == .ErrorUnion and23776 return sema.addConstant(ty, value);
23777 } else if (child.zigTypeTag() == .Pointer and
23778 child.ptrSize() == .One and
23779 child.childType().eql(concrete_ty, sema.mod))
23780 {
23781 const ty = Type.Tag.bound_fn.init();
23782 const value = try Value.Tag.bound_fn.create(arena, .{
23783 .func_inst = decl_val,
23784 .arg0_inst = object_ptr,
23785 });
23786 return sema.addConstant(ty, value);
23787 }
23788 } else if (first_param_type.zigTypeTag() == .ErrorUnion and
23778 first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod))23789 first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod))
23779 {23790 {
23780 const deref = try sema.analyzeLoad(block, src, object_ptr, src);23791 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
test/behavior/fn.zig+17
...@@ -455,6 +455,23 @@ test "method call with optional and error union first param" {...@@ -455,6 +455,23 @@ test "method call with optional and error union first param" {
455 try s.errUnion();455 try s.errUnion();
456}456}
457457
458test "method call with optional pointer first param" {
459 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
460 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
461
462 const S = struct {
463 x: i32 = 1234,
464
465 fn method(s: ?*@This()) !void {
466 try expect(s.?.x == 1234);
467 }
468 };
469 var s: S = .{};
470 try s.method();
471 const s_ptr = &s;
472 try s_ptr.method();
473}
474
458test "using @ptrCast on function pointers" {475test "using @ptrCast on function pointers" {
459 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO476 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
460 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO477 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO