mirror of
https://github.com/golang/go
synced 2024-11-25 06:57:58 -07:00
cmd/gc: fix computation of equality class of types.
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
This commit is contained in:
parent
efced7c6e9
commit
428ea6865c
@ -615,23 +615,23 @@ algtype1(Type *t, Type **bad)
|
||||
return -1; // needs special compare
|
||||
|
||||
case TSTRUCT:
|
||||
if(t->type != T && t->type->down == T) {
|
||||
if(t->type != T && t->type->down == T && !isblanksym(t->type->sym)) {
|
||||
// One-field struct is same as that one field alone.
|
||||
return algtype1(t->type->type, bad);
|
||||
}
|
||||
ret = AMEM;
|
||||
for(t1=t->type; t1!=T; t1=t1->down) {
|
||||
// Blank fields and padding must be ignored,
|
||||
// so need special compare.
|
||||
if(isblanksym(t1->sym) || ispaddedfield(t1, t->width)) {
|
||||
// All fields must be comparable.
|
||||
a = algtype1(t1->type, bad);
|
||||
if(a == ANOEQ)
|
||||
return ANOEQ;
|
||||
|
||||
// Blank fields, padded fields, fields with non-memory
|
||||
// equality need special compare.
|
||||
if(a != AMEM || isblanksym(t1->sym) || ispaddedfield(t1, t->width)) {
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
a = algtype1(t1->type, bad);
|
||||
if(a == ANOEQ)
|
||||
return ANOEQ; // not comparable
|
||||
if(a != AMEM)
|
||||
ret = -1; // needs special compare
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -27,6 +27,10 @@ func (T) _() {
|
||||
func (T) _() {
|
||||
}
|
||||
|
||||
type U struct {
|
||||
_ struct{ a, b, c int }
|
||||
}
|
||||
|
||||
const (
|
||||
c0 = iota
|
||||
_
|
||||
@ -116,6 +120,13 @@ func main() {
|
||||
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)
|
||||
|
@ -13,9 +13,16 @@ var t struct {
|
||||
_ int
|
||||
}
|
||||
|
||||
type T struct {
|
||||
_ []int
|
||||
}
|
||||
|
||||
func main() {
|
||||
_() // ERROR "cannot use _ as value"
|
||||
x := _+1 // ERROR "cannot use _ as value"
|
||||
_ = x
|
||||
_ = t._ // ERROR "cannot refer to blank field"
|
||||
|
||||
var v1, v2 T
|
||||
_ = v1 == v2 // ERROR "cannot be compared|non-comparable"
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ func main() {
|
||||
{
|
||||
var x = struct {
|
||||
x int
|
||||
_ []int
|
||||
_ string
|
||||
y float64
|
||||
_ float64
|
||||
z int
|
||||
|
@ -53,7 +53,7 @@ func main() {
|
||||
|
||||
// Comparison of structs should have a good message
|
||||
use(t3 == t3) // ERROR "struct|expected"
|
||||
use(t4 == t4) // ok; the []int is a blank field
|
||||
use(t4 == t4) // ERROR "cannot be compared|non-comparable"
|
||||
|
||||
// Slices, functions, and maps too.
|
||||
var x []int
|
||||
|
18
test/fixedbugs/issue5698.go
Normal file
18
test/fixedbugs/issue5698.go
Normal file
@ -0,0 +1,18 @@
|
||||
// errorcheck
|
||||
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Issue 5698: can define a key type with slices.
|
||||
|
||||
package main
|
||||
|
||||
type Key struct {
|
||||
a int16 // the compiler was confused by the padding.
|
||||
b []int
|
||||
}
|
||||
|
||||
type Val struct{}
|
||||
|
||||
type Map map[Key]Val // ERROR "invalid map key type"
|
Loading…
Reference in New Issue
Block a user