mirror of
https://github.com/golang/go
synced 2024-11-17 13:54:46 -07:00
428ea6865c
A struct with a single field was considered as equivalent to the field type, which is incorrect is the field is blank. Fields with padding could make the compiler think some types are comparable when they are not. Fixes #5698. R=rsc, golang-dev, daniel.morsing, bradfitz, gri, r CC=golang-dev https://golang.org/cl/10271046
191 lines
2.2 KiB
Go
191 lines
2.2 KiB
Go
// run
|
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Test behavior of the blank identifier (_).
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
"unsafe"
|
|
)
|
|
|
|
import _ "fmt"
|
|
|
|
var call string
|
|
|
|
type T struct {
|
|
_, _, _ int
|
|
}
|
|
|
|
func (T) _() {
|
|
}
|
|
|
|
func (T) _() {
|
|
}
|
|
|
|
type U struct {
|
|
_ struct{ a, b, c int }
|
|
}
|
|
|
|
const (
|
|
c0 = iota
|
|
_
|
|
_
|
|
_
|
|
c4
|
|
)
|
|
|
|
var ints = []string{
|
|
"1",
|
|
"2",
|
|
"3",
|
|
}
|
|
|
|
func f() (int, int) {
|
|
call += "f"
|
|
return 1, 2
|
|
}
|
|
|
|
func g() (float64, float64) {
|
|
call += "g"
|
|
return 3, 4
|
|
}
|
|
|
|
func h(_ int, _ float64) {
|
|
}
|
|
|
|
func i() int {
|
|
call += "i"
|
|
return 23
|
|
}
|
|
|
|
var _ = i()
|
|
|
|
func main() {
|
|
if call != "i" {
|
|
panic("init did not run")
|
|
}
|
|
call = ""
|
|
_, _ = f()
|
|
a, _ := f()
|
|
if a != 1 {
|
|
panic(a)
|
|
}
|
|
b, _ := g()
|
|
if b != 3 {
|
|
panic(b)
|
|
}
|
|
_, a = f()
|
|
if a != 2 {
|
|
panic(a)
|
|
}
|
|
_, b = g()
|
|
if b != 4 {
|
|
panic(b)
|
|
}
|
|
_ = i()
|
|
if call != "ffgfgi" {
|
|
panic(call)
|
|
}
|
|
if c4 != 4 {
|
|
panic(c4)
|
|
}
|
|
|
|
out := ""
|
|
for _, s := range ints {
|
|
out += s
|
|
}
|
|
if out != "123" {
|
|
panic(out)
|
|
}
|
|
|
|
sum := 0
|
|
for s := range ints {
|
|
sum += s
|
|
}
|
|
if sum != 3 {
|
|
panic(sum)
|
|
}
|
|
|
|
// exp/ssa/interp doesn't yet skip blank fields in struct
|
|
// equivalence. It also cannot support unsafe.Pointer.
|
|
if os.Getenv("GOSSAINTERP") == "" {
|
|
type T1 struct{ x, y, z int }
|
|
t1 := *(*T)(unsafe.Pointer(&T1{1, 2, 3}))
|
|
t2 := *(*T)(unsafe.Pointer(&T1{4, 5, 6}))
|
|
if t1 != t2 {
|
|
panic("T{} != T{}")
|
|
}
|
|
|
|
var u1, u2 interface{}
|
|
u1 = *(*U)(unsafe.Pointer(&T1{1, 2, 3}))
|
|
u2 = *(*U)(unsafe.Pointer(&T1{4, 5, 6}))
|
|
if u1 != u2 {
|
|
panic("U{} != U{}")
|
|
}
|
|
}
|
|
|
|
h(a, b)
|
|
|
|
m()
|
|
}
|
|
|
|
type I interface {
|
|
M(_ int, y int)
|
|
}
|
|
|
|
type TI struct{}
|
|
|
|
func (_ TI) M(x int, y int) {
|
|
if x != y {
|
|
println("invalid M call:", x, y)
|
|
panic("bad M")
|
|
}
|
|
}
|
|
|
|
var fp = func(_ int, y int) {}
|
|
|
|
func init() {
|
|
fp = fp1
|
|
}
|
|
|
|
func fp1(x, y int) {
|
|
if x != y {
|
|
println("invalid fp1 call:", x, y)
|
|
panic("bad fp1")
|
|
}
|
|
}
|
|
|
|
func m() {
|
|
var i I
|
|
|
|
i = TI{}
|
|
i.M(1, 1)
|
|
i.M(2, 2)
|
|
|
|
fp(1, 1)
|
|
fp(2, 2)
|
|
}
|
|
|
|
// useless but legal
|
|
var _ int = 1
|
|
var _ = 2
|
|
var _, _ = 3, 4
|
|
|
|
const _ = 3
|
|
const _, _ = 4, 5
|
|
|
|
type _ int
|
|
|
|
func _() {
|
|
panic("oops")
|
|
}
|
|
|
|
func ff() {
|
|
var _ int = 1
|
|
}
|