[dev.typeparams] go/types: implement close(ch) where ch is of type parameter type

This is a port of CL 333713 to go/types.

Change-Id: I517f52592f65cc76e11a12d9148b20c12d9e3e81
Reviewed-on: https://go-review.googlesource.com/c/go/+/335077
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Rob Findley 2021-07-16 20:30:45 -04:00 committed by Robert Findley
parent 19b4142f24
commit cf7e66b7d4
4 changed files with 61 additions and 28 deletions

View file

@ -217,19 +217,23 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
case _Close: case _Close:
// close(c) // close(c)
c := asChan(x.typ) if !underIs(x.typ, func(u Type) bool {
if c == nil { uch, _ := u.(*Chan)
check.invalidArg(x, _InvalidClose, "%s is not a channel", x) if uch == nil {
check.invalidOp(x, _InvalidClose, "cannot close non-channel %s", x)
return false
}
if uch.dir == RecvOnly {
check.invalidOp(x, _InvalidClose, "cannot close receive-only channel %s", x)
return false
}
return true
}) {
return return
} }
if c.dir == RecvOnly {
check.invalidArg(x, _InvalidClose, "%s must not be a receive-only channel", x)
return
}
x.mode = novalue x.mode = novalue
if check.Types != nil { if check.Types != nil {
check.recordBuiltinType(call.Fun, makeSig(nil, c)) check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
} }
case _Complex: case _Complex:

View file

@ -6,6 +6,45 @@
package builtins package builtins
// close
type C0 interface{ int }
type C1 interface{ chan int }
type C2 interface{ chan int | <-chan int }
type C3 interface{ chan int | chan float32 }
type C4 interface{ chan int | chan<- int }
type C5[T any] interface{ ~chan T | chan<- T }
func _[T any](ch T) {
close(ch /* ERROR cannot close non-channel */)
}
func _[T C0](ch T) {
close(ch /* ERROR cannot close non-channel */)
}
func _[T C1](ch T) {
close(ch)
}
func _[T C2](ch T) {
close(ch /* ERROR cannot close receive-only channel */)
}
func _[T C3](ch T) {
close(ch)
}
func _[T C4](ch T) {
close(ch)
}
func _[T C5[X], X any](ch T) {
close(ch)
}
// make
type Bmc interface { type Bmc interface {
~map[rune]string | ~chan int ~map[rune]string | ~chan int
} }
@ -22,31 +61,31 @@ type Bss interface {
~[]int | ~[]string ~[]int | ~[]string
} }
func _[T any] () { func _[T any]() {
_ = make(T /* ERROR invalid argument */ ) _ = make(T /* ERROR invalid argument */)
_ = make(T /* ERROR invalid argument */ , 10) _ = make(T /* ERROR invalid argument */, 10)
_ = make(T /* ERROR invalid argument */ , 10, 20) _ = make(T /* ERROR invalid argument */, 10, 20)
} }
func _[T Bmc] () { func _[T Bmc]() {
_ = make(T) _ = make(T)
_ = make(T, 10) _ = make(T, 10)
_ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20) _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20)
} }
func _[T Bms] () { func _[T Bms]() {
_ = make /* ERROR expects 2 arguments */ (T) _ = make /* ERROR expects 2 arguments */ (T)
_ = make(T, 10) _ = make(T, 10)
_ = make /* ERROR expects 2 arguments */ (T, 10, 20) _ = make /* ERROR expects 2 arguments */ (T, 10, 20)
} }
func _[T Bcs] () { func _[T Bcs]() {
_ = make /* ERROR expects 2 arguments */ (T) _ = make /* ERROR expects 2 arguments */ (T)
_ = make(T, 10) _ = make(T, 10)
_ = make /* ERROR expects 2 arguments */ (T, 10, 20) _ = make /* ERROR expects 2 arguments */ (T, 10, 20)
} }
func _[T Bss] () { func _[T Bss]() {
_ = make /* ERROR expects 2 or 3 arguments */ (T) _ = make /* ERROR expects 2 or 3 arguments */ (T)
_ = make(T, 10) _ = make(T, 10)
_ = make(T, 10, 20) _ = make(T, 10, 20)

View file

@ -144,7 +144,7 @@ func close1() {
var r <-chan int var r <-chan int
close() // ERROR not enough arguments close() // ERROR not enough arguments
close(1, 2) // ERROR too many arguments close(1, 2) // ERROR too many arguments
close(42 /* ERROR not a channel */) close(42 /* ERROR cannot close non-channel */)
close(r /* ERROR receive-only channel */) close(r /* ERROR receive-only channel */)
close(c) close(c)
_ = close /* ERROR used as value */ (c) _ = close /* ERROR used as value */ (c)

View file

@ -105,11 +105,6 @@ func asPointer(t Type) *Pointer {
return op return op
} }
func asTuple(t Type) *Tuple {
op, _ := optype(t).(*Tuple)
return op
}
func asSignature(t Type) *Signature { func asSignature(t Type) *Signature {
op, _ := optype(t).(*Signature) op, _ := optype(t).(*Signature)
return op return op
@ -120,11 +115,6 @@ func asMap(t Type) *Map {
return op return op
} }
func asChan(t Type) *Chan {
op, _ := optype(t).(*Chan)
return op
}
// If the argument to asInterface, asNamed, or asTypeParam is of the respective type // If the argument to asInterface, asNamed, or asTypeParam is of the respective type
// (possibly after expanding an instance type), these methods return that type. // (possibly after expanding an instance type), these methods return that type.
// Otherwise the result is nil. // Otherwise the result is nil.