mirror of
https://github.com/golang/go
synced 2024-11-24 03:30:18 -07:00
cmd/compile/internal/types2: remove tparamIsIface flag and corresponding dead code
Added/clarified some comments. Change-Id: Ib08d3343ff08c23cc8880a27a0148d1ff077a80f Reviewed-on: https://go-review.googlesource.com/c/go/+/363654 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
bc0b98eeff
commit
787708a6ff
@ -179,28 +179,10 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
||||
}
|
||||
|
||||
case *Interface:
|
||||
if tparamIsIface && isTypeParam(x.typ) {
|
||||
if t.typeSet().underIs(func(t Type) bool {
|
||||
switch t := arrayPtrDeref(t).(type) {
|
||||
case *Basic:
|
||||
if isString(t) && id == _Len {
|
||||
return true
|
||||
}
|
||||
case *Array, *Slice, *Chan:
|
||||
return true
|
||||
case *Map:
|
||||
if id == _Len {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}) {
|
||||
mode = value
|
||||
}
|
||||
if !isTypeParam(x.typ) {
|
||||
break
|
||||
}
|
||||
case *TypeParam:
|
||||
assert(!tparamIsIface)
|
||||
if t.underIs(func(t Type) bool {
|
||||
if t.typeSet().underIs(func(t Type) bool {
|
||||
switch t := arrayPtrDeref(t).(type) {
|
||||
case *Basic:
|
||||
if isString(t) && id == _Len {
|
||||
@ -820,9 +802,6 @@ func hasVarSize(t Type) bool {
|
||||
}
|
||||
case *Interface:
|
||||
return isTypeParam(t)
|
||||
case *TypeParam:
|
||||
assert(!tparamIsIface)
|
||||
return true
|
||||
case *Named, *Union:
|
||||
unreachable()
|
||||
}
|
||||
|
@ -673,6 +673,10 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel
|
||||
check.later(func() {
|
||||
for i, bound := range bounds {
|
||||
if isTypeParam(bound) {
|
||||
// We may be able to allow this since it is now well-defined what
|
||||
// the underlying type and thus type set of a type parameter is.
|
||||
// But we may need some additional form of cycle detection within
|
||||
// type parameter lists.
|
||||
check.error(posers[i], "cannot use a type parameter as constraint")
|
||||
}
|
||||
}
|
||||
|
@ -659,7 +659,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
|
||||
newType, val, code := check.implicitTypeAndValue(x, target)
|
||||
if code != 0 {
|
||||
t := target
|
||||
if !tparamIsIface || !isTypeParam(target) {
|
||||
if !isTypeParam(target) {
|
||||
t = safeUnderlying(target)
|
||||
}
|
||||
check.invalidConversion(code, x, t)
|
||||
@ -741,19 +741,8 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
|
||||
default:
|
||||
return nil, nil, _InvalidUntypedConversion
|
||||
}
|
||||
case *TypeParam:
|
||||
assert(!tparamIsIface)
|
||||
if !u.underIs(func(u Type) bool {
|
||||
if u == nil {
|
||||
return false
|
||||
}
|
||||
t, _, _ := check.implicitTypeAndValue(x, u)
|
||||
return t != nil
|
||||
}) {
|
||||
return nil, nil, _InvalidUntypedConversion
|
||||
}
|
||||
case *Interface:
|
||||
if tparamIsIface && isTypeParam(target) {
|
||||
if isTypeParam(target) {
|
||||
if !u.typeSet().underIs(func(u Type) bool {
|
||||
if u == nil {
|
||||
return false
|
||||
|
@ -100,97 +100,14 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
|
||||
return false
|
||||
|
||||
case *Interface:
|
||||
// Note: The body of this 'if' statement is the same as the body
|
||||
// of the case for type parameters below. If we keep both
|
||||
// these branches we should factor out the code.
|
||||
if tparamIsIface && isTypeParam(x.typ) {
|
||||
// TODO(gri) report detailed failure cause for better error messages
|
||||
var key, elem Type // key != nil: we must have all maps
|
||||
mode := variable // non-maps result mode
|
||||
// TODO(gri) factor out closure and use it for non-typeparam cases as well
|
||||
if typ.typeSet().underIs(func(u Type) bool {
|
||||
l := int64(-1) // valid if >= 0
|
||||
var k, e Type // k is only set for maps
|
||||
switch t := u.(type) {
|
||||
case *Basic:
|
||||
if isString(t) {
|
||||
e = universeByte
|
||||
mode = value
|
||||
}
|
||||
case *Array:
|
||||
l = t.len
|
||||
e = t.elem
|
||||
if x.mode != variable {
|
||||
mode = value
|
||||
}
|
||||
case *Pointer:
|
||||
if t, _ := under(t.base).(*Array); t != nil {
|
||||
l = t.len
|
||||
e = t.elem
|
||||
}
|
||||
case *Slice:
|
||||
e = t.elem
|
||||
case *Map:
|
||||
k = t.key
|
||||
e = t.elem
|
||||
}
|
||||
if e == nil {
|
||||
return false
|
||||
}
|
||||
if elem == nil {
|
||||
// first type
|
||||
length = l
|
||||
key, elem = k, e
|
||||
return true
|
||||
}
|
||||
// all map keys must be identical (incl. all nil)
|
||||
// (that is, we cannot mix maps with other types)
|
||||
if !Identical(key, k) {
|
||||
return false
|
||||
}
|
||||
// all element types must be identical
|
||||
if !Identical(elem, e) {
|
||||
return false
|
||||
}
|
||||
// track the minimal length for arrays, if any
|
||||
if l >= 0 && l < length {
|
||||
length = l
|
||||
}
|
||||
return true
|
||||
}) {
|
||||
// For maps, the index expression must be assignable to the map key type.
|
||||
if key != nil {
|
||||
index := check.singleIndex(e)
|
||||
if index == nil {
|
||||
x.mode = invalid
|
||||
return false
|
||||
}
|
||||
var k operand
|
||||
check.expr(&k, index)
|
||||
check.assignment(&k, key, "map index")
|
||||
// ok to continue even if indexing failed - map element type is known
|
||||
x.mode = mapindex
|
||||
x.typ = elem
|
||||
x.expr = e
|
||||
return false
|
||||
}
|
||||
|
||||
// no maps
|
||||
valid = true
|
||||
x.mode = mode
|
||||
x.typ = elem
|
||||
}
|
||||
if !isTypeParam(x.typ) {
|
||||
break
|
||||
}
|
||||
case *TypeParam:
|
||||
// Note: The body of this case is the same as the body of the 'if'
|
||||
// statement in the interface case above. If we keep both
|
||||
// these branches we should factor out the code.
|
||||
// TODO(gri) report detailed failure cause for better error messages
|
||||
assert(!tparamIsIface)
|
||||
var key, elem Type // key != nil: we must have all maps
|
||||
mode := variable // non-maps result mode
|
||||
// TODO(gri) factor out closure and use it for non-typeparam cases as well
|
||||
if typ.underIs(func(u Type) bool {
|
||||
if typ.typeSet().underIs(func(u Type) bool {
|
||||
l := int64(-1) // valid if >= 0
|
||||
var k, e Type // k is only set for maps
|
||||
switch t := u.(type) {
|
||||
|
@ -131,13 +131,7 @@ func comparable(T Type, seen map[Type]bool) bool {
|
||||
case *Array:
|
||||
return comparable(t.elem, seen)
|
||||
case *Interface:
|
||||
if tparamIsIface && isTypeParam(T) {
|
||||
return t.IsComparable()
|
||||
}
|
||||
return true
|
||||
case *TypeParam:
|
||||
assert(!tparamIsIface)
|
||||
return t.iface().IsComparable()
|
||||
return !isTypeParam(T) || t.IsComparable()
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -150,15 +144,7 @@ func hasNil(t Type) bool {
|
||||
case *Slice, *Pointer, *Signature, *Map, *Chan:
|
||||
return true
|
||||
case *Interface:
|
||||
if tparamIsIface && isTypeParam(t) {
|
||||
return u.typeSet().underIs(func(u Type) bool {
|
||||
return u != nil && hasNil(u)
|
||||
})
|
||||
}
|
||||
return true
|
||||
case *TypeParam:
|
||||
assert(!tparamIsIface)
|
||||
return u.underIs(func(u Type) bool {
|
||||
return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool {
|
||||
return u != nil && hasNil(u)
|
||||
})
|
||||
}
|
||||
|
@ -67,7 +67,9 @@ func (s *StdSizes) Alignof(T Type) int64 {
|
||||
case *Slice, *Interface:
|
||||
// Multiword data structures are effectively structs
|
||||
// in which each element has size WordSize.
|
||||
assert(!tparamIsIface || !isTypeParam(T))
|
||||
// Type parameters lead to variable sizes/alignments;
|
||||
// StdSizes.Alignof won't be called for them.
|
||||
assert(!isTypeParam(T))
|
||||
return s.WordSize
|
||||
case *Basic:
|
||||
// Strings are like slices and interfaces.
|
||||
@ -152,6 +154,9 @@ func (s *StdSizes) Sizeof(T Type) int64 {
|
||||
offsets := s.Offsetsof(t.fields)
|
||||
return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
|
||||
case *Interface:
|
||||
// Type parameters lead to variable sizes/alignments;
|
||||
// StdSizes.Sizeof won't be called for them.
|
||||
assert(!isTypeParam(T))
|
||||
return s.WordSize * 2
|
||||
case *TypeParam, *Union:
|
||||
unreachable()
|
||||
|
@ -156,11 +156,8 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
|
||||
}
|
||||
case *Pointer:
|
||||
check.error(embeddedPos, "embedded field type cannot be a pointer")
|
||||
case *TypeParam:
|
||||
assert(!tparamIsIface)
|
||||
check.error(embeddedPos, "embedded field type cannot be a (pointer to a) type parameter")
|
||||
case *Interface:
|
||||
if tparamIsIface && isTypeParam(t) {
|
||||
if isTypeParam(t) {
|
||||
check.error(embeddedPos, "embedded field type cannot be a (pointer to a) type parameter")
|
||||
break
|
||||
}
|
||||
|
@ -25,9 +25,7 @@ func under(t Type) Type {
|
||||
case *Named:
|
||||
return t.under()
|
||||
case *TypeParam:
|
||||
if tparamIsIface {
|
||||
return t.iface()
|
||||
}
|
||||
return t.iface()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
@ -6,12 +6,6 @@ package types2
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// If set, the underlying type of a type parameter is
|
||||
// is the underlying type of its type constraint, i.e.,
|
||||
// an interface. With that, a type parameter satisfies
|
||||
// isInterface.
|
||||
const tparamIsIface = true
|
||||
|
||||
// Note: This is a uint32 rather than a uint64 because the
|
||||
// respective 64 bit atomic instructions are not available
|
||||
// on all platforms.
|
||||
@ -76,10 +70,7 @@ func (t *TypeParam) SetConstraint(bound Type) {
|
||||
}
|
||||
|
||||
func (t *TypeParam) Underlying() Type {
|
||||
if tparamIsIface {
|
||||
return t.iface()
|
||||
}
|
||||
return t
|
||||
return t.iface()
|
||||
}
|
||||
|
||||
func (t *TypeParam) String() string { return TypeString(t, nil) }
|
||||
@ -102,15 +93,11 @@ func (t *TypeParam) iface() *Interface {
|
||||
return &emptyInterface
|
||||
}
|
||||
case *Interface:
|
||||
if tparamIsIface && isTypeParam(bound) {
|
||||
if isTypeParam(bound) {
|
||||
// error is reported in Checker.collectTypeParams
|
||||
return &emptyInterface
|
||||
}
|
||||
ityp = u
|
||||
case *TypeParam:
|
||||
assert(!tparamIsIface)
|
||||
// error is reported in Checker.collectTypeParams
|
||||
return &emptyInterface
|
||||
}
|
||||
|
||||
// If we don't have an interface, wrap constraint into an implicit interface.
|
||||
|
Loading…
Reference in New Issue
Block a user