Skip to content

Commit 2110362

Browse files
Resolve peer function types
1 parent e437b75 commit 2110362

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-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| {
@@ -6962,7 +6959,25 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
69626959
};
69636960
},
69646961

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

69676982
.enum_or_union => return null, // TODO
69686983

tests/analysis/peer_type_resolution.zig

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,37 @@ pub fn main() !void {
221221
_ = noreturn_1;
222222
// ^^^^^^^^^^ (S)()
223223

224+
const FnCoerce = struct {
225+
fn errorsA() [2]error{A} {
226+
return .{ error.A, error.A };
227+
}
228+
fn errorsAB() [2]error{ A, B } {
229+
return .{ error.A, error.A };
230+
}
231+
fn pointers() [2]*const S {
232+
return .{ &s, &s };
233+
}
234+
fn optionalPointers() [2]?*const S {
235+
return .{ &s, null };
236+
}
237+
};
238+
239+
const fn_coerce_0 = if (runtime_bool) &FnCoerce.errorsA else &FnCoerce.errorsAB;
240+
_ = fn_coerce_0;
241+
// ^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]error{A,B}`
242+
243+
const fn_coerce_1 = if (runtime_bool) &FnCoerce.errorsAB else &FnCoerce.errorsA;
244+
_ = fn_coerce_1;
245+
// ^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]error{A,B}`
246+
247+
const fn_coerce_2 = if (runtime_bool) &FnCoerce.pointers else &FnCoerce.optionalPointers;
248+
_ = fn_coerce_2;
249+
// ^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]?*const S`
250+
251+
const fn_coerce_3 = if (runtime_bool) &FnCoerce.optionalPointers else &FnCoerce.pointers;
252+
_ = fn_coerce_3;
253+
// ^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]?*const S`
254+
224255
// Use @compileLog to verify the expected type with the compiler:
225256
// @compileLog(error_union_0);
226257

@@ -241,6 +272,11 @@ const optional_comptime_float = if (comptime_bool) @as(?comptime_float, 0) else
241272
const null_error_union = if (comptime_bool) @as(error{A}!@TypeOf(null), null) else null;
242273
// ^^^^^^^^^^^^^^^^ (error{A}!@TypeOf(null))()
243274

275+
fn void_fn() void {}
276+
277+
const optional_fn = if (comptime_bool) @as(?fn () void, void_fn) else void_fn;
278+
// ^^^^^^^^^^^ (?fn () void)()
279+
244280
const f32_and_u32 = if (comptime_bool) @as(f32, 0) else @as(i32, 0);
245281
// ^^^^^^^^^^^ (either type)()
246282

0 commit comments

Comments
 (0)