On Tue, 4 Apr 2017 02:40:31 -0700 (PDT)
Paul Jolly <
pa...@myitcv.org.uk> wrote:
> *I couldn't find anything previously on the question below, but as
> ever would appreciate any pointers to prior questions/issues etc.*
>
> Consider the following (playground
> <
https://play.golang.org/p/MQuEfeG5c9>):
>
> ====
> package main
>
> import (
> "fmt"
> )
>
> type S struct {
> f func()
> }
>
> func (s S) Impl() {}
>
> var _ I = S{}
>
> type I interface {
> Impl()
> }
>
> func main() {
> m := make(map[I]bool)
> m[S{}] = true
> fmt.Println(m)
> }
> ====
>
> Per [the spec](
https://golang.org/ref/spec#Map_types):
>
> *If the key type is an interface type, these comparison operators
> must be
> > defined for the dynamic key values; failure will cause a run-time
> > panic.*
>
>
> this program compiles but then fails with a runtime panic.
>
> However, in this instance, at compile time we know by type-checking
> alone the type of the value used to index m (i.e. S{}) and that that
> type is not comparable... and so can conclude that if this line
> executes it will panic.
>
> From a spec perspective, is this a case of keeping the implementation
> and documentation simple, by treating all cases for interface-keyed
> maps the same, i.e. runtime panic?
>
> Or is there some other reason why this case isn't caught by the
> compiler/go vet?
In the sequence
m := make(map[I]bool)
m[S{}] = true
the map "m" stores values of type I; that's all it considers when you
pass values as keys when performing operations on it.
When you insert a value keyed by S{}, the compiler creates a value of
type I which has S as its dynamic type and S{} as its value.
The program as speficied panics with
panic: runtime error: hash of unhashable type main.S
because instances of S are indeed not comparable (because S.f is a
function type) but you could just as fine do
type X struct {
x int
}
func (x X) Impl() {}
m[X{}] = true
and it would work just fine because values of X are comparable, and
still implement I.