Skip to content

Commit 8ea0120

Browse files
committed
[dev.go2go] go/types: interfaces with type lists are only allowed as constraints
Check that such constraint interfaces don't appear in: - composite types - type and function instantiations - assertions - type switches Streamlined respective error messages. Added lots of tests. Fixes #41124. Change-Id: Ie04a95ab056b40561484f04ed6e843ca371e1d41 Reviewed-on: https://go-review.googlesource.com/c/go/+/251718 Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent c4914f1 commit 8ea0120

File tree

8 files changed

+142
-34
lines changed

8 files changed

+142
-34
lines changed

src/go/types/builtins.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
506506
case _New:
507507
// new(T)
508508
// (no argument evaluated yet)
509-
T := check.typ(call.Args[0])
509+
T := check.varType(call.Args[0])
510510
if T == Typ[Invalid] {
511511
return
512512
}

src/go/types/call.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ func (check *Checker) call(x *operand, call *ast.CallExpr) exprKind {
143143
assert(n == len(sig.tparams))
144144

145145
// instantiate function signature
146+
for i, typ := range targs {
147+
// some positions may be missing if types are inferred
148+
var pos token.Pos
149+
if i < len(poslist) {
150+
pos = poslist[i]
151+
}
152+
check.ordinaryType(pos, typ)
153+
}
146154
res := check.instantiate(x.pos(), sig, targs, poslist).(*Signature)
147155
assert(res.tparams == nil) // signature is not generic anymore
148156
x.typ = res

src/go/types/examples/types.go2

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,16 +251,16 @@ type I interface {
251251
}
252252

253253
var (
254-
_ interface /* ERROR cannot contain type constraints */ {type int}
255-
_ I /* ERROR cannot contain type constraints */
254+
_ interface /* ERROR contains type constraints */ {type int}
255+
_ I /* ERROR contains type constraints */
256256
)
257257

258-
func _(I /* ERROR cannot contain type constraints */ )
259-
func _(x, y, z I /* ERROR cannot contain type constraints */ )
260-
func _() I /* ERROR cannot contain type constraints */
258+
func _(I /* ERROR contains type constraints */ )
259+
func _(x, y, z I /* ERROR contains type constraints */ )
260+
func _() I /* ERROR contains type constraints */
261261

262262
func _() {
263-
var _ I /* ERROR cannot contain type constraints */
263+
var _ I /* ERROR contains type constraints */
264264
}
265265

266266
type C interface {

src/go/types/expr.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
11231123
// We have an "open" [...]T array type.
11241124
// Create a new ArrayType with unknown length (-1)
11251125
// and finish setting it up after analyzing the literal.
1126-
typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
1126+
typ = &Array{len: -1, elem: check.varType(atyp.Elt)}
11271127
base = typ
11281128
break
11291129
}
@@ -1335,7 +1335,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
13351335
if isGeneric(x.typ) {
13361336
// type instantiation
13371337
x.mode = invalid
1338-
x.typ = check.typ(e)
1338+
x.typ = check.varType(e)
13391339
if x.typ != Typ[Invalid] {
13401340
x.mode = typexpr
13411341
}
@@ -1590,7 +1590,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
15901590
check.invalidAST(e.Pos(), "use of .(type) outside type switch")
15911591
goto Error
15921592
}
1593-
T := check.typ(e.Type)
1593+
T := check.varType(e.Type)
15941594
if T == Typ[Invalid] {
15951595
goto Error
15961596
}

src/go/types/fixedbugs/issue39634.go2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ func bar8[A foo8[A]](a A) {}
3636
func main8() {}
3737

3838
// crash 9
39-
type foo9[A any] interface { type foo9[A] }
40-
func _() { var _ = new(foo9[int]) }
39+
type foo9[A any] interface { type foo9 /* ERROR interface contains type constraints */ [A] }
40+
func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) }
4141

4242
// crash 12
4343
var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len)]c /* ERROR undeclared */ /* ERROR undeclared */

src/go/types/fixedbugs/issue41124.go2

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2020 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
// Test case from issue.
8+
9+
type Nat interface {
10+
type Zero, Succ
11+
}
12+
13+
type Zero struct{}
14+
type Succ struct{
15+
Nat // ERROR interface contains type constraints
16+
}
17+
18+
// Struct tests.
19+
20+
type I1 interface {
21+
comparable
22+
}
23+
24+
type I2 interface {
25+
type int
26+
}
27+
28+
type I3 interface {
29+
I1
30+
I2
31+
}
32+
33+
type _ struct {
34+
f I1 // ERROR interface is .* comparable
35+
}
36+
37+
type _ struct {
38+
comparable // ERROR interface is .* comparable
39+
}
40+
41+
type _ struct{
42+
I1 // ERROR interface is .* comparable
43+
}
44+
45+
type _ struct{
46+
I2 // ERROR interface contains type constraints
47+
}
48+
49+
type _ struct{
50+
I3 // ERROR interface contains type constraints
51+
}
52+
53+
// General composite types.
54+
55+
type (
56+
_ [10]I1 // ERROR interface is .* comparable
57+
_ [10]I2 // ERROR interface contains type constraints
58+
59+
_ []I1 // ERROR interface is .* comparable
60+
_ []I2 // ERROR interface contains type constraints
61+
62+
_ *I3 // ERROR interface contains type constraints
63+
_ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints
64+
_ chan I3 // ERROR interface contains type constraints
65+
_ func(I1 /* ERROR interface is .* comparable */ )
66+
_ func() I2 // ERROR interface contains type constraints
67+
)
68+
69+
// Other cases.
70+
71+
var _ = [...]I3 /* ERROR interface contains type constraints */ {}
72+
73+
func _(x interface{}) {
74+
_ = x.(I3 /* ERROR interface contains type constraints */ )
75+
}
76+
77+
type T1[_ any] struct{}
78+
type T3[_, _, _ any] struct{}
79+
var _ T1[I2 /* ERROR interface contains type constraints */ ]
80+
var _ T3[int, I2 /* ERROR interface contains type constraints */ , float32]
81+
82+
func f1[_ any]() int
83+
var _ = f1[I2 /* ERROR interface contains type constraints */ ]()
84+
func f3[_, _, _ any]() int
85+
var _ = f3[int, I2 /* ERROR interface contains type constraints */ , float32]()
86+
87+
func _(x interface{}) {
88+
switch x.(type) {
89+
case I2 /* ERROR interface contains type constraints */ :
90+
}
91+
}

src/go/types/stmt.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,9 @@ L:
272272
if T == Typ[Invalid] {
273273
continue L
274274
}
275+
if T != nil {
276+
check.ordinaryType(e.Pos(), T)
277+
}
275278
// look for duplicate types
276279
// (quadratic algorithm, but type switches tend to be reasonably small)
277280
for t, pos := range seen {

src/go/types/typexpr.go

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -124,26 +124,32 @@ func (check *Checker) typ(e ast.Expr) Type {
124124
}
125125

126126
// varType type-checks the type expression e and returns its type, or Typ[Invalid].
127-
// The type must not be an (uninstantiated) generic type and it must not be an
128-
// interface type containing type lists.
127+
// The type must not be an (uninstantiated) generic type and it must be ordinary
128+
// (see ordinaryType).
129129
func (check *Checker) varType(e ast.Expr) Type {
130130
typ := check.definedType(e, nil)
131-
if t := typ.Interface(); t != nil {
132-
// We don't want to complete interfaces while we are in the middle
133-
// of type-checking parameter declarations that might belong to
134-
// interface methods. Delay this check to the end of type-checking.
135-
check.atEnd(func() {
136-
check.completeInterface(e.Pos(), t) // TODO(gri) is this the correct position?
131+
check.ordinaryType(e.Pos(), typ)
132+
return typ
133+
}
134+
135+
// ordinaryType reports an error if typ is an interface type containing
136+
// type lists or is (or embeds) the predeclared type comparable.
137+
func (check *Checker) ordinaryType(pos token.Pos, typ Type) {
138+
// We don't want to call Under() (via Interface) or complete interfaces while we
139+
// are in the middle of type-checking parameter declarations that might belong to
140+
// interface methods. Delay this check to the end of type-checking.
141+
check.atEnd(func() {
142+
if t := typ.Interface(); t != nil {
143+
check.completeInterface(pos, t) // TODO(gri) is this the correct position?
137144
if t.allTypes != nil {
138-
check.softErrorf(e.Pos(), "interface type for variable cannot contain type constraints (%s)", t.allTypes)
145+
check.softErrorf(pos, "interface contains type constraints (%s)", t.allTypes)
139146
return
140147
}
141148
if t.IsComparable() {
142-
check.softErrorf(e.Pos(), "interface type for variable cannot be (or embed) comparable")
149+
check.softErrorf(pos, "interface is (or embeds) comparable")
143150
}
144-
})
145-
}
146-
return typ
151+
}
152+
})
147153
}
148154

149155
// anyType type-checks the type expression e and returns its type, or Typ[Invalid].
@@ -477,13 +483,13 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
477483
typ := new(Array)
478484
def.setUnderlying(typ)
479485
typ.len = check.arrayLength(e.Len)
480-
typ.elem = check.typ(e.Elt)
486+
typ.elem = check.varType(e.Elt)
481487
return typ
482488
}
483489

484490
typ := new(Slice)
485491
def.setUnderlying(typ)
486-
typ.elem = check.typ(e.Elt)
492+
typ.elem = check.varType(e.Elt)
487493
return typ
488494

489495
case *ast.StructType:
@@ -495,7 +501,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
495501
case *ast.StarExpr:
496502
typ := new(Pointer)
497503
def.setUnderlying(typ)
498-
typ.base = check.typ(e.X)
504+
typ.base = check.varType(e.X)
499505
return typ
500506

501507
case *ast.FuncType:
@@ -517,8 +523,8 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
517523
typ := new(Map)
518524
def.setUnderlying(typ)
519525

520-
typ.key = check.typ(e.Key)
521-
typ.elem = check.typ(e.Value)
526+
typ.key = check.varType(e.Key)
527+
typ.elem = check.varType(e.Value)
522528

523529
// spec: "The comparison operators == and != must be fully defined
524530
// for operands of the key type; thus the key type must not be a
@@ -556,7 +562,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
556562
}
557563

558564
typ.dir = dir
559-
typ.elem = check.typ(e.Value)
565+
typ.elem = check.varType(e.Value)
560566
return typ
561567

562568
default:
@@ -670,7 +676,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
670676
func (check *Checker) typeList(list []ast.Expr) []Type {
671677
res := make([]Type, len(list)) // res != nil even if len(list) == 0
672678
for i, x := range list {
673-
t := check.typ(x)
679+
t := check.varType(x)
674680
if t == Typ[Invalid] {
675681
res = nil
676682
}
@@ -1054,7 +1060,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
10541060
}
10551061

10561062
for _, f := range list.List {
1057-
typ = check.typ(f.Type)
1063+
typ = check.varType(f.Type)
10581064
tag = check.tag(f.Tag)
10591065
if len(f.Names) > 0 {
10601066
// named fields
@@ -1134,7 +1140,7 @@ func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) []
11341140
check.invalidAST(pos, "missing type constraint")
11351141
continue
11361142
}
1137-
typ := check.typ(texpr)
1143+
typ := check.varType(texpr)
11381144
// A type constraint may be a predeclared type or a
11391145
// composite type composed of only predeclared types.
11401146
// TODO(gri) If we enable this again it also must run

0 commit comments

Comments
 (0)