golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.34k stars 17.71k forks source link

cmd/go2go: provide better error message when saying that type parameter cannot be embedded in interface #39948

Closed lavalamp closed 4 years ago

lavalamp commented 4 years ago

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

dev.go2go @ 236ad5a2802478cee910bf64bfadf0a28e57ed99

(latest as of a minute ago)

What did you do?

package main

type A interface { A() }
type B interface { B() }
type C interface { C() }

type Mix(type T interface{}, U interface{}) interface {
        T // error: T is not an interface
        U // error: U is not an interface 
}

func main() {
        var abc Mix(Mix(A, B), C)
        _ = abc.A
        _ = abc.B
        _ = abc.C
}

What did you expect to see?

I expected this to compile.

What did you see instead?

Type checking failed, errors on the indicated lines.

lavalamp commented 4 years ago

Note 1: It doesn't matter if you wrap the T and U in parens, e.g. (T).

Note 2: I'm not 100% sure this is supposed to work, but I didn't see it excluded in the spec. Also if it's not supposed to work an error message that specifically says so would be good.

jimmyfrasche commented 4 years ago

The constraints on T and U don't restrict them to be interfaces just any type that satisfies the empty interface (which is all of them).

I don't know if there is a way to do this. If there is I would have expected interface{ type interface{} } to be it, but that did not work either: https://go2goplay.golang.org/p/vkJYmEWG2dV

lavalamp commented 4 years ago

Yeah I just came to the same conclusion, reading the spec I think there is no way to constrain the type to only interface types? That seems like maybe a spec problem and not (only) an implementation problem.

ianlancetaylor commented 4 years ago

The type checking errors for the original program are:

type checking failed for main
foo.go2:8:9: T is not an interface
foo.go2:9:9: U is not an interface

That's correct. The type constraint for T is interface{}, which means that it has no constraint: it can be any type. You can't embed any type in an interface type, you can only embed an interface type.

In the current design draft there is no way to write a type constraint that says that a type must be an interface type. Whether this is a real problem depends on why people would want to write that requirement.

Closing because there is no issue. General discussion of the design draft should take place on golang-nuts, not on the issue tracker. Thanks.

lavalamp commented 4 years ago

Changing the error message to "is not constrained to interface" or "is not only an interface" would give folks like me a big clue about the real problem.

ianlancetaylor commented 4 years ago

OK, reopening as a request for a better error message.

lavalamp commented 4 years ago

Thanks!

gopherbot commented 4 years ago

Change https://golang.org/cl/240520 mentions this issue: [dev.go2go] go/types: better error message when confusing a type parameter with an interface

griesemer commented 4 years ago

Fixed on dev.go2go.