[generics] Infer types on return

92 views
Skip to first unread message

Brandon Bennett

unread,
Jun 19, 2020, 3:44:02 PM6/19/20
to golang-nuts
I was playing around with a, probably not good, idea of what a rust-like Return type would look like: https://go2goplay.golang.org/p/k0NKN9Q6Wc1

It seems when we are returning a specific value like Result(int) from a function as in

func myFunc(input string) Result(int) {
        return Err(int)(ErrBadValue)
}

That it would be nice if we didn't have to specify Err(int) and that it could be inferred from the return type instead.

Ian Lance Taylor

unread,
Jun 19, 2020, 4:37:54 PM6/19/20
to Brandon Bennett, golang-nuts
If I'm reading this right, you are suggesting that because the result
of Err is being assigned to a value of type Result(int) (via the
return statement) we should be able to use that fact to infer the type
argument of Err. I think that would be possible for cases where we
are assigning to a variable of known type. It's a little more
confusing when using := to assign to a variable whose type is not yet
known. And it also seems unlikely to work when assigning to a
variable of interface type.

That is, I think we could make it work. I would just want to be very
sure that it would never be confusing. I think it's important that it
always be very very clear exactly what types got inferred, and how.

Thanks for the suggestion.

Ian

Axel Wagner

unread,
Jun 19, 2020, 5:40:42 PM6/19/20
to Ian Lance Taylor, Brandon Bennett, golang-nuts
On Fri, Jun 19, 2020 at 10:37 PM Ian Lance Taylor <ia...@golang.org> wrote:
On Fri, Jun 19, 2020 at 12:44 PM Brandon Bennett <ben...@gmail.com> wrote:
>
> I was playing around with a, probably not good, idea of what a rust-like Return type would look like: https://go2goplay.golang.org/p/k0NKN9Q6Wc1
>
> It seems when we are returning a specific value like Result(int) from a function as in
>
> func myFunc(input string) Result(int) {
>         return Err(int)(ErrBadValue)
> }
>
> That it would be nice if we didn't have to specify Err(int) and that it could be inferred from the return type instead.

If I'm reading this right, you are suggesting that because the result
of Err is being assigned to a value of type Result(int) (via the
return statement) we should be able to use that fact to infer the type
argument of Err.  I think that would be possible for cases where we
are assigning to a variable of known type.  It's a little more
confusing when using := to assign to a variable whose type is not yet
known.  And it also seems unlikely to work when assigning to a
variable of interface type.

I think the solution to this would probably be the same as if you use `x := nil` - a compiler-error stating that there can't be a type assigned to the RHS. I think it would be fine to just require type-annotations where we can't clearly and unambiguously infer a type, as long as those cases are understandable - the two examples seem easy to understand exceptions, so as long as not more come up, that would still be fine IMO.

That being said, I assume you generally see the value in more type-inference and I trust you to come up with decent rules for this eventually :)

I'm wondering what fundamentally separates inference of arguments from inference of returns, FWIW. Why is it a problem if we try to infer the return-type when assigning to an interface, but not when we try to infer the parameter-type when passing one?
 

That is, I think we could make it work.  I would just want to be very
sure that it would never be confusing.  I think it's important that it
always be very very clear exactly what types got inferred, and how.

Thanks for the suggestion.

Ian

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcWKLjyQ8AsQ13%2Bwx%3DJeKR19Du0j0jfyqnKTTMUxjCitHQ%40mail.gmail.com.

Ian Lance Taylor

unread,
Jun 19, 2020, 7:03:27 PM6/19/20
to Axel Wagner, Brandon Bennett, golang-nuts
On Fri, Jun 19, 2020 at 2:40 PM Axel Wagner
<axel.wa...@googlemail.com> wrote:
>
> On Fri, Jun 19, 2020 at 10:37 PM Ian Lance Taylor <ia...@golang.org> wrote:
>>
>> On Fri, Jun 19, 2020 at 12:44 PM Brandon Bennett <ben...@gmail.com> wrote:
>> >
>> > I was playing around with a, probably not good, idea of what a rust-like Return type would look like: https://go2goplay.golang.org/p/k0NKN9Q6Wc1
>> >
>> > It seems when we are returning a specific value like Result(int) from a function as in
>> >
>> > func myFunc(input string) Result(int) {
>> > return Err(int)(ErrBadValue)
>> > }
>> >
>> > That it would be nice if we didn't have to specify Err(int) and that it could be inferred from the return type instead.
>>
>> If I'm reading this right, you are suggesting that because the result
>> of Err is being assigned to a value of type Result(int) (via the
>> return statement) we should be able to use that fact to infer the type
>> argument of Err. I think that would be possible for cases where we
>> are assigning to a variable of known type. It's a little more
>> confusing when using := to assign to a variable whose type is not yet
>> known. And it also seems unlikely to work when assigning to a
>> variable of interface type.
>
>
> I think the solution to this would probably be the same as if you use `x := nil` - a compiler-error stating that there can't be a type assigned to the RHS. I think it would be fine to just require type-annotations where we can't clearly and unambiguously infer a type, as long as those cases are understandable - the two examples seem easy to understand exceptions, so as long as not more come up, that would still be fine IMO.
>
> That being said, I assume you generally see the value in more type-inference and I trust you to come up with decent rules for this eventually :)
>
> I'm wondering what fundamentally separates inference of arguments from inference of returns, FWIW. Why is it a problem if we try to infer the return-type when assigning to an interface, but not when we try to infer the parameter-type when passing one?

The difference is the directionality. Argument passing is like
assignment. When I write "a = b", and b has an interface type, then a
also has to have an interface type. So type inference for passing an
argument means that passing an interface type (b) gives you an
interface type (a). But for results it's the other way around. Now
we know type a and we are trying to infer type b. And when a has an
interface type, b can be anything that implements that interface. As
you say, we can simply reject the case. We pretty much have to. But
it might be confusing that we can do inference for some result type
buts not others. And it's a kind of confusion that arises only for
results, not for arguments.

Ian

Michael Jones

unread,
Jun 19, 2020, 9:05:20 PM6/19/20
to Ian Lance Taylor, Axel Wagner, Brandon Bennett, golang-nuts
> I'm wondering what fundamentally separates inference of arguments from inference of returns, FWIW. Why is it a problem if we try to infer the return-type when assigning to an interface, but not when we try to infer the parameter-type when passing one?
 
The difference is the directionality.  Argument passing is like
assignment.  When I write "a = b", and b has an interface type, then a
also has to have an interface type.  So type inference for passing an
argument means that passing an interface type (b) gives you an
interface type (a).  But for results it's the other way around.  Now
we know type a and we are trying to infer type b.  And when a has an
interface type, b can be anything that implements that interface.  As
you say, we can simply reject the case.  We pretty much have to.  But
it might be confusing that we can do inference for some result type
but not others.  And it's a kind of confusion that arises only for
results, not for arguments.

It is a situation that seems easily explainable, so teachable.

The single possibility case "specific = specific" says this about inference:
unknown = specific, infer unknown matches specific
specific = unknown, infer unknown matches specific

The multiple possibility cases are as you say:
unknown = nonspecific, infer unknown matches nonspecific (identical interfaces)
nonspecific = unknown, no inference possible; unknown may be any of multiple possibilities.

The teachable maxim is: "can infer from single choice; cannot infer from multiple choices"

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.


--
Michael T. Jones
michae...@gmail.com
Reply all
Reply to author
Forward
0 new messages