Skip to content

Commit c5dbceb

Browse files
Resolve peer function types
1 parent b593e78 commit c5dbceb

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

src/analysis.zig

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,6 +2279,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) error
22792279
var buf: [1]Ast.Node.Index = undefined;
22802280
const fn_proto = tree.fullFnProto(&buf, node).?;
22812281

2282+
// TODO: should we avoid calling innermostContainer if this is a function type?
22822283
const container_type = options.container_type orelse try analyser.innermostContainer(handle, tree.tokenStart(fn_proto.ast.fn_token));
22832284
const doc_comments = try getDocComments(analyser.arena, tree, node);
22842285
const name = if (fn_proto.name_token) |t| tree.tokenSlice(t) else null;
@@ -3097,8 +3098,6 @@ pub const Type = struct {
30973098
}
30983099
},
30993100
.function => |info| {
3100-
std.hash.autoHash(hasher, info.fn_token);
3101-
hasher.update(info.handle.uri);
31023101
info.container_type.hashWithHasher(hasher);
31033102
for (info.parameters) |param| {
31043103
param.type.hashWithHasher(hasher);
@@ -3178,8 +3177,6 @@ pub const Type = struct {
31783177
},
31793178
.function => |a_info| {
31803179
const b_info = b.function;
3181-
if (a_info.fn_token != b_info.fn_token) return false;
3182-
if (!std.mem.eql(u8, a_info.handle.uri, b_info.handle.uri)) return false;
31833180
if (!a_info.container_type.eql(b_info.container_type.*)) return false;
31843181
if (a_info.parameters.len != b_info.parameters.len) return false;
31853182
for (a_info.parameters, b_info.parameters) |a_param, b_param| {
@@ -6967,7 +6964,25 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
69676964
};
69686965
},
69696966

6970-
.func => return null, // TODO
6967+
.func => {
6968+
var opt_cur_ty: ?Type = null;
6969+
for (peer_tys) |opt_ty| {
6970+
const ty = opt_ty orelse continue;
6971+
const cur_ty = opt_cur_ty orelse {
6972+
opt_cur_ty = ty;
6973+
continue;
6974+
};
6975+
if (ty.zigTypeTag(analyser).? != .@"fn") {
6976+
return null;
6977+
}
6978+
if (cur_ty.eql(ty)) {
6979+
continue;
6980+
}
6981+
// TODO: coerce function types
6982+
return null;
6983+
}
6984+
return opt_cur_ty.?;
6985+
},
69716986

69726987
.enum_or_union => return null, // TODO
69736988

tests/analysis/peer_type_resolution.zig

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,33 @@ const error_union_26 = if (runtime_bool) @as(error{A}!i8, 0) else @as(i16, 0);
162162
const error_union_27 = if (runtime_bool) @as(i16, 0) else @as(error{A}!i8, 0);
163163
// ^^^^^^^^^^^^^^ (error{A}!i16)()
164164

165+
const FnCoerce = struct {
166+
fn errorsA() [2]error{A} {
167+
return .{ error.A, error.A };
168+
}
169+
fn errorsAB() [2]error{ A, B } {
170+
return .{ error.A, error.A };
171+
}
172+
fn pointers() [2]*const S {
173+
return .{ &s, &s };
174+
}
175+
fn optionalPointers() [2]?*const S {
176+
return .{ &s, null };
177+
}
178+
};
179+
180+
const fn_coerce_0 = if (runtime_bool) &FnCoerce.errorsA else &FnCoerce.errorsAB;
181+
// ^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]error{A,B}`
182+
183+
const fn_coerce_1 = if (runtime_bool) &FnCoerce.errorsAB else &FnCoerce.errorsA;
184+
// ^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]error{A,B}`
185+
186+
const fn_coerce_2 = if (runtime_bool) &FnCoerce.pointers else &FnCoerce.optionalPointers;
187+
// ^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]?*const S`
188+
189+
const fn_coerce_3 = if (runtime_bool) &FnCoerce.optionalPointers else &FnCoerce.pointers;
190+
// ^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]?*const S`
191+
165192
test "noreturn" {
166193
const noreturn_0 = if (runtime_bool) s else return;
167194
_ = noreturn_0;
@@ -186,6 +213,11 @@ const optional_comptime_float = if (comptime_bool) @as(?comptime_float, 0) else
186213
const null_error_union = if (comptime_bool) @as(error{A}!@TypeOf(null), null) else null;
187214
// ^^^^^^^^^^^^^^^^ (error{A}!@TypeOf(null))()
188215

216+
fn void_fn() void {}
217+
218+
const optional_fn = if (comptime_bool) @as(?fn () void, void_fn) else void_fn;
219+
// ^^^^^^^^^^^ (?fn () void)()
220+
189221
const f32_and_u32 = if (comptime_bool) @as(f32, 0) else @as(i32, 0);
190222
// ^^^^^^^^^^^ (either type)()
191223

0 commit comments

Comments
 (0)