diff --git a/src/value.zig b/src/value.zig index 50f86c7e79..0580d7cd3c 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2391,12 +2391,15 @@ pub const Value = extern union { union_obj.val.hash(active_field_ty, hasher, mod); }, .Fn => { - const func: *Module.Fn = val.castTag(.function).?.data; - // Note that his hashes the *Fn rather than the *Decl. This is + // Note that his hashes the *Fn/*ExternFn rather than the *Decl. This is // to differentiate function bodies from function pointers. // This is currently redundant since we already hash the zig type tag // at the top of this function. - std.hash.autoHash(hasher, func); + if (val.castTag(.function)) |func| { + std.hash.autoHash(hasher, func.data); + } else if (val.castTag(.extern_fn)) |func| { + std.hash.autoHash(hasher, func.data); + } else unreachable; }, .Frame => { @panic("TODO implement hashing frame values"); diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index a82456aa70..b3c399cea8 100644 --- a/test/behavior/generics.zig +++ b/test/behavior/generics.zig @@ -358,3 +358,14 @@ test "nested generic function" { try expect(@typeInfo(@TypeOf(S.g)).Fn.is_generic); try S.foo(u32, S.bar, 123); } + +test "extern function used as generic parameter" { + const S = struct { + extern fn foo() void; + extern fn bar() void; + inline fn baz(comptime _: anytype) type { + return struct {}; + } + }; + try expect(S.baz(S.foo) != S.baz(S.bar)); +}