Skip to content

Commit b95bff0

Browse files
committed
go/types: remove tparamIsIface flag and corresponding dead code
This is a port of CL 363654 from types2 to go/types. Change-Id: I64041615ccc7f11f2e4ae395b063ec5141ccf2cf Reviewed-on: https://go-review.googlesource.com/c/go/+/364896 Trust: Robert Findley <[email protected]> Run-TryBot: Robert Findley <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 9115a7b commit b95bff0

9 files changed

Lines changed: 27 additions & 169 deletions

File tree

src/go/types/builtins.go

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -180,28 +180,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
180180
}
181181

182182
case *Interface:
183-
if tparamIsIface && isTypeParam(x.typ) {
184-
if t.typeSet().underIs(func(t Type) bool {
185-
switch t := arrayPtrDeref(t).(type) {
186-
case *Basic:
187-
if isString(t) && id == _Len {
188-
return true
189-
}
190-
case *Array, *Slice, *Chan:
191-
return true
192-
case *Map:
193-
if id == _Len {
194-
return true
195-
}
196-
}
197-
return false
198-
}) {
199-
mode = value
200-
}
183+
if !isTypeParam(x.typ) {
184+
break
201185
}
202-
case *TypeParam:
203-
assert(!tparamIsIface)
204-
if t.underIs(func(t Type) bool {
186+
if t.typeSet().underIs(func(t Type) bool {
205187
switch t := arrayPtrDeref(t).(type) {
206188
case *Basic:
207189
if isString(t) && id == _Len {
@@ -829,9 +811,6 @@ func hasVarSize(t Type) bool {
829811
}
830812
case *Interface:
831813
return isTypeParam(t)
832-
case *TypeParam:
833-
assert(!tparamIsIface)
834-
return true
835814
case *Named, *Union:
836815
unreachable()
837816
}

src/go/types/decl.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,10 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList
725725
check.later(func() {
726726
for i, bound := range bounds {
727727
if isTypeParam(bound) {
728+
// We may be able to allow this since it is now well-defined what
729+
// the underlying type and thus type set of a type parameter is.
730+
// But we may need some additional form of cycle detection within
731+
// type parameter lists.
728732
check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint")
729733
}
730734
}

src/go/types/expr.go

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
599599
newType, val, code := check.implicitTypeAndValue(x, target)
600600
if code != 0 {
601601
t := target
602-
if !tparamIsIface || !isTypeParam(target) {
602+
if !isTypeParam(target) {
603603
t = safeUnderlying(target)
604604
}
605605
check.invalidConversion(code, x, t)
@@ -680,23 +680,8 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
680680
default:
681681
return nil, nil, _InvalidUntypedConversion
682682
}
683-
case *TypeParam:
684-
assert(!tparamIsIface)
685-
if !u.underIs(func(u Type) bool {
686-
if u == nil {
687-
return false
688-
}
689-
t, _, _ := check.implicitTypeAndValue(x, u)
690-
return t != nil
691-
}) {
692-
return nil, nil, _InvalidUntypedConversion
693-
}
694-
// keep nil untyped (was bug #39755)
695-
if x.isNil() {
696-
return Typ[UntypedNil], nil, 0
697-
}
698683
case *Interface:
699-
if tparamIsIface && isTypeParam(target) {
684+
if isTypeParam(target) {
700685
if !u.typeSet().underIs(func(u Type) bool {
701686
if u == nil {
702687
return false

src/go/types/index.go

Lines changed: 3 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -101,97 +101,14 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst
101101
return false
102102

103103
case *Interface:
104-
// Note: The body of this 'if' statement is the same as the body
105-
// of the case for type parameters below. If we keep both
106-
// these branches we should factor out the code.
107-
if tparamIsIface && isTypeParam(x.typ) {
108-
// TODO(gri) report detailed failure cause for better error messages
109-
var key, elem Type // key != nil: we must have all maps
110-
mode := variable // non-maps result mode
111-
// TODO(gri) factor out closure and use it for non-typeparam cases as well
112-
if typ.typeSet().underIs(func(u Type) bool {
113-
l := int64(-1) // valid if >= 0
114-
var k, e Type // k is only set for maps
115-
switch t := u.(type) {
116-
case *Basic:
117-
if isString(t) {
118-
e = universeByte
119-
mode = value
120-
}
121-
case *Array:
122-
l = t.len
123-
e = t.elem
124-
if x.mode != variable {
125-
mode = value
126-
}
127-
case *Pointer:
128-
if t, _ := under(t.base).(*Array); t != nil {
129-
l = t.len
130-
e = t.elem
131-
}
132-
case *Slice:
133-
e = t.elem
134-
case *Map:
135-
k = t.key
136-
e = t.elem
137-
}
138-
if e == nil {
139-
return false
140-
}
141-
if elem == nil {
142-
// first type
143-
length = l
144-
key, elem = k, e
145-
return true
146-
}
147-
// all map keys must be identical (incl. all nil)
148-
// (that is, we cannot mix maps with other types)
149-
if !Identical(key, k) {
150-
return false
151-
}
152-
// all element types must be identical
153-
if !Identical(elem, e) {
154-
return false
155-
}
156-
// track the minimal length for arrays, if any
157-
if l >= 0 && l < length {
158-
length = l
159-
}
160-
return true
161-
}) {
162-
// For maps, the index expression must be assignable to the map key type.
163-
if key != nil {
164-
index := check.singleIndex(e)
165-
if index == nil {
166-
x.mode = invalid
167-
return false
168-
}
169-
var k operand
170-
check.expr(&k, index)
171-
check.assignment(&k, key, "map index")
172-
// ok to continue even if indexing failed - map element type is known
173-
x.mode = mapindex
174-
x.typ = elem
175-
x.expr = e
176-
return false
177-
}
178-
179-
// no maps
180-
valid = true
181-
x.mode = mode
182-
x.typ = elem
183-
}
104+
if !isTypeParam(x.typ) {
105+
break
184106
}
185-
case *TypeParam:
186-
// Note: The body of this case is the same as the body of the 'if'
187-
// statement in the interface case above. If we keep both
188-
// these branches we should factor out the code.
189107
// TODO(gri) report detailed failure cause for better error messages
190-
assert(!tparamIsIface)
191108
var key, elem Type // key != nil: we must have all maps
192109
mode := variable // non-maps result mode
193110
// TODO(gri) factor out closure and use it for non-typeparam cases as well
194-
if typ.underIs(func(u Type) bool {
111+
if typ.typeSet().underIs(func(u Type) bool {
195112
l := int64(-1) // valid if >= 0
196113
var k, e Type // k is only set for maps
197114
switch t := u.(type) {

src/go/types/predicates.go

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,7 @@ func comparable(T Type, seen map[Type]bool) bool {
133133
case *Array:
134134
return comparable(t.elem, seen)
135135
case *Interface:
136-
if tparamIsIface && isTypeParam(T) {
137-
return t.IsComparable()
138-
}
139-
return true
140-
case *TypeParam:
141-
assert(!tparamIsIface)
142-
return t.iface().IsComparable()
136+
return !isTypeParam(T) || t.IsComparable()
143137
}
144138
return false
145139
}
@@ -152,15 +146,7 @@ func hasNil(t Type) bool {
152146
case *Slice, *Pointer, *Signature, *Map, *Chan:
153147
return true
154148
case *Interface:
155-
if tparamIsIface && isTypeParam(t) {
156-
return u.typeSet().underIs(func(u Type) bool {
157-
return u != nil && hasNil(u)
158-
})
159-
}
160-
return true
161-
case *TypeParam:
162-
assert(!tparamIsIface)
163-
return u.underIs(func(u Type) bool {
149+
return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool {
164150
return u != nil && hasNil(u)
165151
})
166152
}

src/go/types/sizes.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ func (s *StdSizes) Alignof(T Type) int64 {
6767
case *Slice, *Interface:
6868
// Multiword data structures are effectively structs
6969
// in which each element has size WordSize.
70-
assert(!tparamIsIface || !isTypeParam(T))
70+
// Type parameters lead to variable sizes/alignments;
71+
// StdSizes.Alignof won't be called for them.
72+
assert(!isTypeParam(T))
7173
return s.WordSize
7274
case *Basic:
7375
// Strings are like slices and interfaces.
@@ -152,6 +154,9 @@ func (s *StdSizes) Sizeof(T Type) int64 {
152154
offsets := s.Offsetsof(t.fields)
153155
return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
154156
case *Interface:
157+
// Type parameters lead to variable sizes/alignments;
158+
// StdSizes.Sizeof won't be called for them.
159+
assert(!isTypeParam(T))
155160
return s.WordSize * 2
156161
case *TypeParam, *Union:
157162
unreachable()

src/go/types/struct.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,14 +155,11 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
155155
}
156156
case *Pointer:
157157
check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer")
158-
case *TypeParam:
159-
assert(!tparamIsIface)
160-
// This error code here is inconsistent with other error codes for
161-
// invalid embedding, because this restriction may be relaxed in the
162-
// future, and so it did not warrant a new error code.
163-
check.error(embeddedPos, _MisplacedTypeParam, "embedded field type cannot be a (pointer to a) type parameter")
164158
case *Interface:
165-
if tparamIsIface && isTypeParam(t) {
159+
if isTypeParam(t) {
160+
// The error code here is inconsistent with other error codes for
161+
// invalid embedding, because this restriction may be relaxed in the
162+
// future, and so it did not warrant a new error code.
166163
check.error(embeddedPos, _MisplacedTypeParam, "embedded field type cannot be a (pointer to a) type parameter")
167164
break
168165
}

src/go/types/type.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ func under(t Type) Type {
2525
case *Named:
2626
return t.under()
2727
case *TypeParam:
28-
if tparamIsIface {
29-
return t.iface()
30-
}
28+
return t.iface()
3129
}
3230
return t
3331
}

src/go/types/typeparam.go

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@ import (
99
"sync/atomic"
1010
)
1111

12-
// If set, the underlying type of a type parameter is
13-
// is the underlying type of its type constraint, i.e.,
14-
// an interface. With that, a type parameter satisfies
15-
// isInterface.
16-
const tparamIsIface = true
17-
1812
// Note: This is a uint32 rather than a uint64 because the
1913
// respective 64 bit atomic instructions are not available
2014
// on all platforms.
@@ -79,10 +73,7 @@ func (t *TypeParam) SetConstraint(bound Type) {
7973
}
8074

8175
func (t *TypeParam) Underlying() Type {
82-
if tparamIsIface {
83-
return t.iface()
84-
}
85-
return t
76+
return t.iface()
8677
}
8778

8879
func (t *TypeParam) String() string { return TypeString(t, nil) }
@@ -105,15 +96,11 @@ func (t *TypeParam) iface() *Interface {
10596
return &emptyInterface
10697
}
10798
case *Interface:
108-
if tparamIsIface && isTypeParam(bound) {
99+
if isTypeParam(bound) {
109100
// error is reported in Checker.collectTypeParams
110101
return &emptyInterface
111102
}
112103
ityp = u
113-
case *TypeParam:
114-
assert(!tparamIsIface)
115-
// error is reported in Checker.collectTypeParams
116-
return &emptyInterface
117104
}
118105

119106
// If we don't have an interface, wrap constraint into an implicit interface.

0 commit comments

Comments
 (0)