Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Cannot use .this" error when using _ for multiple type parameters in method declaration

Tags:

generics

go

I am playing around with type parameters (generics) using Go 1.18beta1.

Problem

Consider the following snippet:

package main

import (
    "fmt"
)

func main() {
    foo := &Foo[string, int]{
        valueA: "i am a string",
        valueB: 123,
    }
    fmt.Println(foo)
}

type Foo[T1 any, T2 any] struct {
    valueA T1
    valueB T2
}

func (f *Foo[_,_]) String() string {
    return fmt.Sprintf("%v %v", f.valueA, f.valueB)
}

This snippet fails to build with the following error:

<autogenerated>:1: cannot use .this (type *Foo[string,int]) as type *Foo[go.shape.string_0,go.shape.string_0] in argument to (*Foo[go.shape.string_0,go.shape.int_1]).String

I attempted to use _ in the method declaration because of the following statement in the Type Parameters Proposal:

The type parameters listed in a method declaration need not have the same names as the type parameters in the type declaration. In particular, if they are not used by the method, they can be _.

Question

Is the build error above a bug in 1.18beta1 or am I missing something?

Snippet variations that build successfully

Use type parameter names

I can make the code build successfully if I change the String method declaration to the following (replace the _ with actual type parameters):

func (f *Foo[T1,T2]) String() string {
    return fmt.Sprintf("%v %v", f.valueA, f.valueB)
}

Single type parameter

I managed to use the _ successfully when only using a single type parameter:

package main

import (
    "fmt"
)

func main() {
    foo := &Foo[string]{"i am a string"}

    fmt.Println(foo)
}

type Foo[T1 any] struct {
    value T1
}

func (f *Foo[_]) String() string {
    return fmt.Sprintf("%v", f.value)
}

Instantiate Foo with same type for T1 and T2

_ also works in method declaration if Foo is instantiated with the same type (e.g. string for both T1 and T2):

package main

import (
    "fmt"
)

func main() {
    foo := &Foo[string, string]{
        valueA: "i am a string",
        valueB: "i am also a string",
    }
    fmt.Println(foo)
}

type Foo[T1 any, T2 any] struct {
    valueA T1
    valueB T2
}

func (f *Foo[_,_]) String() string {
    return fmt.Sprintf("%v %v", f.valueA, f.valueB)
}
like image 369
Sam Herrmann Avatar asked May 30 '26 18:05

Sam Herrmann


1 Answers

As mentioned in the comments of the question, the described behavior is a bug in Go 1.18beta1 and is being tracked by issue 50419.

Edit

I have confirmed that the bug in question is fixed in 1.18beta2, which was released on 31 January, 2022.

like image 86
Sam Herrmann Avatar answered Jun 01 '26 06:06

Sam Herrmann



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!