go: cmd/compile: inconsistent behaviors in judging whether or not two types are identical

Please answer these questions before submitting your issue. Thanks!

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

go version go1.10.1 linux/amd64

Does this issue reproduce with the latest release?

yes

What did you do?

package m3

import "time"

type t = time.Time
type T = time.Time

type A = struct{t}
type B = struct{T}
import "m3"
import "time"

type t = time.Time
type T = time.Time

type A = struct{t}
type B = struct{T}

func main() {
   var a, b interface{} = m3.A{}, m3.B{}
   var x, y interface{} = A{}, B{}
   println(a == x) // true
   println(b == y) // true
   
   _ = A(m3.A{}) // cannot convert struct { time.Time } literal (type struct { time.Time }) to type struct { time.Time }
   _ = B(m3.B{}) // ok
   
   println(a == b) // true
   println(x == y) // true
   _ = B(A{})       // cannot convert struct { time.Time } literal (type struct { time.Time }) to type struct { time.Time }
   _ = m3.A(m3.B{}) // cannot convert struct { time.Time } literal (type struct { time.Time }) to type struct { time.Time }
}

What did you expect to see?

No errors, [edit: or all println calls, except the second, print false].

What did you see instead?

./main.go:18:9: cannot convert struct { time.Time } literal (type struct { time.Time }) to type struct { time.Time }
./main.go:23:9: cannot convert struct { time.Time } literal (type struct { time.Time }) to type struct { time.Time }
./main.go:24:12: cannot convert struct { time.Time } literal (type struct { time.Time }) to type struct { time.Time }

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 27 (18 by maintainers)

Most upvoted comments

  1. Two struct types with differently named (corresponding) embedded fields are different types, even if the embedded field types are identical. So the assignments a = b are expected to be reported as invalid at compile time.

  2. Because of 1), runtime interface comparison of a and b values should return false, but the issue is that (basically) the same printing code that’s used in the error message (and which prints both types as struct{ int }) is used to identify those types’ symbols, so the type information is incorrect.

If the error messages are correct, the problem is bigger:

package main

import (
	"fmt"
	"time"
)

type t = time.Time
type T = time.Time

type A = struct{ t }
type B = struct{ T }

func main() {
	var a A
	var b B
	fmt.Println(interface{}(b) == interface{}(a)) // true
	//fmt.Println(b == a)
}