Sema: make method call work with optionals and error unions

Closes #13414
This commit is contained in:
Veikka Tuominen 2022-11-04 18:13:49 +02:00
parent 35afa3fd8b
commit 42db468dcb
2 changed files with 41 additions and 1 deletions

View File

@ -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,

View File

@ -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();
}