authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-04 18:13:49+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-04 23:13:49+02:00
log42db468dcb3de15426f9f8ec8da78e36155e3510
treeeb0ed437afeb6c02b8a5add1943a8ec1ec02e011
parent35afa3fd8bdc140baf9d135711833e836de04d86

Sema: make method call work with optionals and error unions

Closes #13414

2 files changed, 41 insertions(+), 1 deletions(-)

src/Sema.zig+22-1
......@@ -22833,6 +22833,7 @@ fn fieldCallBind(
2283322833 {
2283422834 const first_param_type = decl_type.fnParamType(0);
2283522835 const first_param_tag = first_param_type.tag();
22836 var opt_buf: Type.Payload.ElemType = undefined;
2283622837 // zig fmt: off
2283722838 if (first_param_tag == .var_args_param or
2283822839 first_param_tag == .generic_poison or (
......@@ -22851,7 +22852,27 @@ fn fieldCallBind(
2285122852 });
2285222853 return sema.addConstant(ty, value);
2285322854 } else if (first_param_type.eql(concrete_ty, sema.mod)) {
22854 var deref = try sema.analyzeLoad(block, src, object_ptr, src);
22855 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
22856 const ty = Type.Tag.bound_fn.init();
22857 const value = try Value.Tag.bound_fn.create(arena, .{
22858 .func_inst = decl_val,
22859 .arg0_inst = deref,
22860 });
22861 return sema.addConstant(ty, value);
22862 } else if (first_param_tag != .generic_poison and first_param_type.zigTypeTag() == .Optional and
22863 first_param_type.optionalChild(&opt_buf).eql(concrete_ty, sema.mod))
22864 {
22865 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
22866 const ty = Type.Tag.bound_fn.init();
22867 const value = try Value.Tag.bound_fn.create(arena, .{
22868 .func_inst = decl_val,
22869 .arg0_inst = deref,
22870 });
22871 return sema.addConstant(ty, value);
22872 } else if (first_param_tag != .generic_poison and first_param_type.zigTypeTag() == .ErrorUnion and
22873 first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod))
22874 {
22875 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
2285522876 const ty = Type.Tag.bound_fn.init();
2285622877 const value = try Value.Tag.bound_fn.create(arena, .{
2285722878 .func_inst = decl_val,
test/behavior/fn.zig+19
......@@ -434,3 +434,22 @@ test "implicit cast function to function ptr" {
434434 var fnPtr2: *const fn () callconv(.C) c_int = S2.someFunctionThatReturnsAValue;
435435 try expect(fnPtr2() == 123);
436436}
437
438test "method call with optional and error union first param" {
439 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
441
442 const S = struct {
443 x: i32 = 1234,
444
445 fn opt(s: ?@This()) !void {
446 try expect(s.?.x == 1234);
447 }
448 fn errUnion(s: anyerror!@This()) !void {
449 try expect((try s).x == 1234);
450 }
451 };
452 var s: S = .{};
453 try s.opt();
454 try s.errUnion();
455}