Question about type unification/inference for non-constants

48 views
Skip to first unread message

Kevin Chowski

unread,
Jan 31, 2026, 1:01:02 PM (23 hours ago) Jan 31
to golang-nuts
Hi all, I read through the spec to look for the rules about this but I think this is a consequence of a couple different parts, so I'm reaching out here for some expert help. I'm also wondering if the current state of affairs is due to a hard limitation or simply because "no one has found time to work on it yet".

Why doesn't type inference choose a named type when it is an obvious candidate, and could it be enhanced to do so without too much trouble? What I mean: https://play.golang.com/p/gWMOBr-rMgq

(btw, if you're surprised to see `var myFunc MyFunc = f` works correctly in that above link, it's because there are special assignment rules for *some* unnamed types, but not all; to be clear, I understand none of these work for MyInt and I (believe I) know why it's a good thing: https://play.golang.com/p/iN0Tz5i480A)

Staving off "why do you even want this?": I want to do (something like) this because I have a lisp implementation where you can register typesafe builtins from Go code, and I'm trying to emulate variable type parameters so that instead of calling CompileFunc1 for functions with 1 argument, CompileFunc2 for those with 2, etc, I can just use some CompileFuncN and have the type inference magically sort out the right type for me :) So I do already have a relatively simple way to handle this and don't need a new workaround, but I want to understand why I can't do something else.

Ian Lance Taylor

unread,
Jan 31, 2026, 1:40:58 PM (23 hours ago) Jan 31
to Kevin Chowski, golang-nuts
This line:

func WithTypeParameter[F MyFunc](f F) {}

says that WithTypeParameter requires a type argument that matches
MyFunc. There is only such type argument, namely MyFunc itself. That
seems useless, so I don't understand your goal. We could probably add
an inference rule saying that if the type of the argument is
assignable to the type parameter constraint (when the constraint is
not an interface type), then use the type parameter constraint. But
approximately zero real programs would use that, because approximately
zero real programs would use a type parameter that only accepts a
single type argument.

Ian

Kevin Chowski

unread,
Jan 31, 2026, 3:35:05 PM (21 hours ago) Jan 31
to golang-nuts
Thanks for the quick reply, Ian. You're right, my simplified example doesn't make sense on its own. It's really about giving the WithTypeParameter more than one option in the type list, which allows that single function to accept func types with different numbers of type parameters, in a way that maintains static typing AND attaches useful methods to these func closures for dynamic checking later in the compilation sequence. This example (which requires us to spell out some types, since inference doesn't work) shows the sort of catch-all function I want to write: https://play.golang.com/p/MtKjQdV-RmP

Maybe there's a different reason why THIS wouldn't work :)

Again, I /can/ just manually convert my func literals to the named Func0/Func1[T1]/Func2[T1, T2]/etc types, but since they all have type parameters it is really verbose, and better to have a func to intercept instead. E.g. this (https://play.golang.com/p/mlh9P6wNKEY) is essentially what I'm doing today; there is an extra call to WrapFunc0/WrapFunc1/etc for each builtin type. Boo! It's obviously not a big deal, but I also have some dreams of figuring out how to do vararg type parameters with whatever functionality we have today, and I believe this is one avenue to reduce what boilerplate may be required to do it. Or maybe that's just a pipe dream!)

Ian Lance Taylor

unread,
Jan 31, 2026, 5:48:51 PM (19 hours ago) Jan 31
to Kevin Chowski, golang-nuts
On Sat, Jan 31, 2026 at 12:35 PM Kevin Chowski <Ke...@chowski.com> wrote:
>
> Thanks for the quick reply, Ian. You're right, my simplified example doesn't make sense on its own. It's really about giving the WithTypeParameter more than one option in the type list, which allows that single function to accept func types with different numbers of type parameters, in a way that maintains static typing AND attaches useful methods to these func closures for dynamic checking later in the compilation sequence. This example (which requires us to spell out some types, since inference doesn't work) shows the sort of catch-all function I want to write: https://play.golang.com/p/MtKjQdV-RmP
>
> Maybe there's a different reason why THIS wouldn't work :)
>
> Again, I /can/ just manually convert my func literals to the named Func0/Func1[T1]/Func2[T1, T2]/etc types, but since they all have type parameters it is really verbose, and better to have a func to intercept instead. E.g. this (https://play.golang.com/p/mlh9P6wNKEY) is essentially what I'm doing today; there is an extra call to WrapFunc0/WrapFunc1/etc for each builtin type. Boo! It's obviously not a big deal, but I also have some dreams of figuring out how to do vararg type parameters with whatever functionality we have today, and I believe this is one avenue to reduce what boilerplate may be required to do it. Or maybe that's just a pipe dream!)

I see. I don't see how to make this work. In particular the compiler
is going to want to infer the Func1 argument type, but if you are
using Func0 then there is no such type.

Ian
Reply all
Reply to author
Forward
0 new messages