Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: infer parameter type from arguments in call to result function #64197

Open
pat42smith opened this issue Nov 16, 2023 · 1 comment
Open
Labels
generics Issue is related to generics Proposal TypeInference Issue is related to generic type inference
Milestone

Comments

@pat42smith
Copy link

Suppose we have a generic function F whose result type is a function. In an expression that calls F and immediately calls the result function, it would be nice to use the arguments to the result function to help determine the type parameters for F.

For example, consider:

func check[X any](t *testing.T) func(X, error) X {
	return func(x X, e error) X {
		if e != nil {
			t.Helper()
			t.Fatal(e)
		}
		return x
	}
}

f := check(t)(os.Open("path"))

In Go 1.21.4, this does not compile; the error is "cannot infer X". But there is only one reasonable choice for X: *os.File. In principle, the compiler could figure this out; I don't know how difficult it would be in practice.

In this specific example, the problem can be worked around by changing the order of parameter lists:

func vet[X any](x X, e error) func(t *testing.T) X {
	// obvious content omitted
)

f := vet(os.Open("path"))(t)

However, I find this order much less desirable, for various reasons not relevant here. And there are undoubtedly cases where such a workaround is not possible. In particular, if both parameter lists use type parameters:

func foo[X, Y any](X) func(Y) { ... }

then there seems to be no way to write a call foo(x)(y) without explicitly specifying at least one type parameter.

Like #50285 (comment), this seems to be a request to infer types from the context of a function call, although in a different manner.

There would be some open questions about how far this might go. Could we have

f(1)(2)(3)(4)(5)(6)("seven")

where "seven" is used to infer a type parameter of f? What if the result type is not a function, but the expression calls a method on the result? Should this work?

type Box[T any] struct{}

func (b Box[T]) hold(T) {}

func crate[T any]() Box[T] {
	return Box[T]{}
}

func oops() {
	crate().hold("some string")
}
@gopherbot gopherbot added this to the Proposal milestone Nov 16, 2023
@earthboundkid
Copy link
Contributor

See https://github.com/carlmjohnson/be/pull/9/files where I made a test helper like check, but had to reverse the arguments to make it work with inference. I never merged the PR because the API is awkward with the arguments reversed.

@seankhliao seankhliao changed the title Proposal: infer parameter type from arguments in call to result funtion proposal: infer parameter type from arguments in call to result function Nov 16, 2023
@seankhliao seankhliao added generics Issue is related to generics TypeInference Issue is related to generic type inference labels Nov 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
generics Issue is related to generics Proposal TypeInference Issue is related to generic type inference
Projects
Status: Incoming
Development

No branches or pull requests

4 participants