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

go/types, types2: better error message when using *interface instead of interface #48312

Open
zllangct opened this issue Sep 10, 2021 · 2 comments
Open
Assignees
Labels
Milestone

Comments

@zllangct
Copy link

@zllangct zllangct commented Sep 10, 2021

What version of Go are you using (go version)?

$ go version
go version devel go1.18-b32209d22d Thu Sep 9 23:18:18 2021 +0000 windows/amd64

What did you do?

package main

import (
	"fmt"
)

type ISetName interface {
	SetName(name string)
}

type Item struct {
	Name string
}


func (i *Item) SetName(name string)  {
	i.Name = name
}

func Hello[T ISetName]()  {
	ins := new(T)
	(ins).SetName("foo")
        fmt.Printf("%+v", ins)
}

func main() {
	Hello[Item]()
}

What did you expect to see?

output: {Name:"foo"}

What did you see instead?

// go version devel go1.18-b32209d22d
output:Item does not satisfy ISetName: wrong method signature
	got  func (*Item).SetName(name string)
	want func (ISetName).SetName(name string)
// go2go playground
output:Item does not satisfy ISetName: wrong method signature
	got  func (*Item).SetName(name string)
	want func (ISetName).SetName(name string)

when method 'SetName' with value receiver is ok, but pointer receiver not

package main

import (
	"fmt"
)

type ISetName interface {
	SetName(name string)
}

type Item struct {
	Name string
}


func (i Item) SetName(name string)  {
	i.Name = name
}

func Hello[T ISetName]()  {
	ins := new(T)
	(ins).SetName("foo")
        fmt.Printf("%+v", ins)
}

func main() {
	Hello[Item]()
}
// go version devel go1.18-b32209d22d
output: error: cannot convert ins (variable of type *T) to ISetName
// go2go playground
output:&{Name:}

It is seem that go2go playroung can work with value receiver method 'SetName', but go version devel go1.18-b32209d22d not.

package main

import (
	"fmt"
)

type ISetName interface {
	SetName(name string)
}

type Item struct {
	Name string
}


func (i Item) SetName(name string)  {
	i.Name = name
}

func Hello[T ISetName]()  {
	ins := new(T)
	(*ins).SetName("foo")
        fmt.Printf("%+v", ins)
}

func main() {
	Hello[Item]()
}
// go version devel go1.18-b32209d22d
output: &{Name:}
@cuonglm
Copy link
Member

@cuonglm cuonglm commented Sep 10, 2021

The error reported is correct, since when you call new(T), this basically a pointer to interface ISetname. If you convert your program to non-generic, and run with go1.17, you will get a clearer error message:

func Hello(T ISetName) {
	ins := &T
	(ins).SetName("foo")
	fmt.Printf("%+v", ins)
}

func main() {
	Hello(&Item{})
}
$ go run t.go
./t.go:21:7: ins.SetName undefined (type *ISetName is pointer to interface, not interface)

Maybe we can make go/types and go/types2 produce a clearer error message.

cc @griesemer @findleyr

@zllangct zllangct closed this Sep 10, 2021
@griesemer griesemer changed the title go/types, types2: wrong method signature go/types, types2: better error message when using *interface instead of interface Sep 10, 2021
@griesemer griesemer self-assigned this Sep 10, 2021
@griesemer griesemer added this to the Go1.18 milestone Sep 10, 2021
@griesemer
Copy link
Contributor

@griesemer griesemer commented Sep 10, 2021

Retitled, looking for better error message.

@griesemer griesemer reopened this Sep 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants