Skip to content

Commit 491edcf

Browse files
Resolve peer types for functions
1 parent e69bc6d commit 491edcf

File tree

2 files changed

+42
-5
lines changed

2 files changed

+42
-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;
@@ -3094,8 +3095,6 @@ pub const Type = struct {
30943095
}
30953096
},
30963097
.function => |info| {
3097-
std.hash.autoHash(hasher, info.fn_token);
3098-
hasher.update(info.handle.uri);
30993098
info.container_type.hashWithHasher(hasher);
31003099
for (info.parameters) |param| {
31013100
param.type.hashWithHasher(hasher);
@@ -3175,8 +3174,6 @@ pub const Type = struct {
31753174
},
31763175
.function => |a_info| {
31773176
const b_info = b.function;
3178-
if (a_info.fn_token != b_info.fn_token) return false;
3179-
if (!std.mem.eql(u8, a_info.handle.uri, b_info.handle.uri)) return false;
31803177
if (!a_info.container_type.eql(b_info.container_type.*)) return false;
31813178
if (a_info.parameters.len != b_info.parameters.len) return false;
31823179
for (a_info.parameters, b_info.parameters) |a_param, b_param| {
@@ -7055,7 +7052,25 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
70557052
};
70567053
},
70577054

7058-
.func => return null, // TODO
7055+
.func => {
7056+
var opt_cur_ty: ?Type = null;
7057+
for (peer_tys) |opt_ty| {
7058+
const ty = opt_ty orelse continue;
7059+
const cur_ty = opt_cur_ty orelse {
7060+
opt_cur_ty = ty;
7061+
continue;
7062+
};
7063+
if (ty.zigTypeTag(analyser).? != .@"fn") {
7064+
return null;
7065+
}
7066+
if (cur_ty.eql(ty)) {
7067+
continue;
7068+
}
7069+
// TODO: coerce function types
7070+
return null;
7071+
}
7072+
return opt_cur_ty.?;
7073+
},
70597074

70607075
.enum_or_union => return null, // TODO
70617076

tests/analysis/peer_type_resolution.zig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,23 @@ pub fn main() !void {
230230
_ = coercible_array_1;
231231
// ^^^^^^^^^^^^^^^^^ (either type)() TODO this should be `[2]?*i32`
232232

233+
const CoercibleFunctions = struct {
234+
fn a() [2]*const S {
235+
return .{ &s, &s };
236+
}
237+
fn b() [2]?*const S {
238+
return .{ &s, null };
239+
}
240+
};
241+
242+
const coercible_function_0 = if (runtime_bool) &CoercibleFunctions.a else &CoercibleFunctions.b;
243+
_ = coercible_function_0;
244+
// ^^^^^^^^^^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]?*const S`
245+
246+
const coercible_function_1 = if (runtime_bool) &CoercibleFunctions.b else &CoercibleFunctions.a;
247+
_ = coercible_function_1;
248+
// ^^^^^^^^^^^^^^^^^^^^ (either type)() TODO this should be `*const fn () [2]?*const S`
249+
233250
// Use @compileLog to verify the expected type with the compiler:
234251
// @compileLog(error_union_0);
235252
}
@@ -248,6 +265,11 @@ const optional_comptime_float = if (comptime_bool) @as(?comptime_float, 0) else
248265
const null_error_union = if (comptime_bool) @as(error{A}!@TypeOf(null), null) else null;
249266
// ^^^^^^^^^^^^^^^^ (error{A}!@TypeOf(null))()
250267

268+
fn void_fn() void {}
269+
270+
const optional_fn = if (comptime_bool) @as(?fn () void, void_fn) else void_fn;
271+
// ^^^^^^^^^^^ (?fn () void)()
272+
251273
const f32_and_u32 = if (comptime_bool) @as(f32, 0) else @as(i32, 0);
252274
// ^^^^^^^^^^^ (either type)()
253275

0 commit comments

Comments
 (0)