diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-11-04 18:13:49 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-11-04 23:13:49 +0200 |
| commit | 42db468dcb3de15426f9f8ec8da78e36155e3510 (patch) | |
| tree | eb0ed437afeb6c02b8a5add1943a8ec1ec02e011 | |
| parent | 35afa3fd8bdc140baf9d135711833e836de04d86 (diff) | |
| download | zig-42db468dcb3de15426f9f8ec8da78e36155e3510.tar.gz zig-42db468dcb3de15426f9f8ec8da78e36155e3510.zip | |
Sema: make method call work with optionals and error unions
Closes #13414
| -rw-r--r-- | src/Sema.zig | 23 | ||||
| -rw-r--r-- | test/behavior/fn.zig | 19 |
2 files changed, 41 insertions, 1 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 08aecb6097..849b0053ac 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -22833,6 +22833,7 @@ fn fieldCallBind( { const first_param_type = decl_type.fnParamType(0); const first_param_tag = first_param_type.tag(); + var opt_buf: Type.Payload.ElemType = undefined; // zig fmt: off if (first_param_tag == .var_args_param or first_param_tag == .generic_poison or ( @@ -22851,7 +22852,27 @@ fn fieldCallBind( }); return sema.addConstant(ty, value); } else if (first_param_type.eql(concrete_ty, sema.mod)) { - var deref = try sema.analyzeLoad(block, src, object_ptr, src); + const deref = try sema.analyzeLoad(block, src, object_ptr, src); + const ty = Type.Tag.bound_fn.init(); + const value = try Value.Tag.bound_fn.create(arena, .{ + .func_inst = decl_val, + .arg0_inst = deref, + }); + return sema.addConstant(ty, value); + } else if (first_param_tag != .generic_poison and first_param_type.zigTypeTag() == .Optional and + first_param_type.optionalChild(&opt_buf).eql(concrete_ty, sema.mod)) + { + const deref = try sema.analyzeLoad(block, src, object_ptr, src); + const ty = Type.Tag.bound_fn.init(); + const value = try Value.Tag.bound_fn.create(arena, .{ + .func_inst = decl_val, + .arg0_inst = deref, + }); + return sema.addConstant(ty, value); + } else if (first_param_tag != .generic_poison and first_param_type.zigTypeTag() == .ErrorUnion and + first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod)) + { + const deref = try sema.analyzeLoad(block, src, object_ptr, src); const ty = Type.Tag.bound_fn.init(); const value = try Value.Tag.bound_fn.create(arena, .{ .func_inst = decl_val, diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index 06127aa855..eb13ccfec2 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -434,3 +434,22 @@ test "implicit cast function to function ptr" { var fnPtr2: *const fn () callconv(.C) c_int = S2.someFunctionThatReturnsAValue; try expect(fnPtr2() == 123); } + +test "method call with optional and error union first param" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + + const S = struct { + x: i32 = 1234, + + fn opt(s: ?@This()) !void { + try expect(s.?.x == 1234); + } + fn errUnion(s: anyerror!@This()) !void { + try expect((try s).x == 1234); + } + }; + var s: S = .{}; + try s.opt(); + try s.errUnion(); +} |
