mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
[dev.typeparams] cmd/compile/internal/types2: implement close(ch) where ch is of type parameter type
Change-Id: I45189468553e83390fd2640b5708c60a7852fbb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/333713 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
6511922a14
commit
5f0ea40c67
5 changed files with 62 additions and 26 deletions
|
@ -212,19 +212,23 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
|
||||
case _Close:
|
||||
// close(c)
|
||||
c := asChan(x.typ)
|
||||
if c == nil {
|
||||
check.errorf(x, invalidArg+"%s is not a channel", x)
|
||||
if !underIs(x.typ, func(u Type) bool {
|
||||
uch, _ := u.(*Chan)
|
||||
if uch == nil {
|
||||
check.errorf(x, invalidOp+"cannot close non-channel %s", x)
|
||||
return false
|
||||
}
|
||||
if uch.dir == RecvOnly {
|
||||
check.errorf(x, invalidOp+"cannot close receive-only channel %s", x)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}) {
|
||||
return
|
||||
}
|
||||
if c.dir == RecvOnly {
|
||||
check.errorf(x, invalidArg+"%s must not be a receive-only channel", x)
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, c))
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
|
||||
}
|
||||
|
||||
case _Complex:
|
||||
|
|
|
@ -6,6 +6,45 @@
|
|||
|
||||
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 {
|
||||
~map[rune]string | ~chan int
|
||||
}
|
||||
|
@ -22,31 +61,31 @@ type Bss interface {
|
|||
~[]int | ~[]string
|
||||
}
|
||||
|
||||
func _[T any] () {
|
||||
_ = make(T /* ERROR invalid argument */ )
|
||||
_ = make(T /* ERROR invalid argument */ , 10)
|
||||
_ = make(T /* ERROR invalid argument */ , 10, 20)
|
||||
func _[T any]() {
|
||||
_ = make(T /* ERROR invalid argument */)
|
||||
_ = make(T /* ERROR invalid argument */, 10)
|
||||
_ = make(T /* ERROR invalid argument */, 10, 20)
|
||||
}
|
||||
|
||||
func _[T Bmc] () {
|
||||
func _[T Bmc]() {
|
||||
_ = make(T)
|
||||
_ = make(T, 10)
|
||||
_ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20)
|
||||
}
|
||||
|
||||
func _[T Bms] () {
|
||||
func _[T Bms]() {
|
||||
_ = make /* ERROR expects 2 arguments */ (T)
|
||||
_ = make(T, 10)
|
||||
_ = make /* ERROR expects 2 arguments */ (T, 10, 20)
|
||||
}
|
||||
|
||||
func _[T Bcs] () {
|
||||
func _[T Bcs]() {
|
||||
_ = make /* ERROR expects 2 arguments */ (T)
|
||||
_ = make(T, 10)
|
||||
_ = make /* ERROR expects 2 arguments */ (T, 10, 20)
|
||||
}
|
||||
|
||||
func _[T Bss] () {
|
||||
func _[T Bss]() {
|
||||
_ = make /* ERROR expects 2 or 3 arguments */ (T)
|
||||
_ = make(T, 10)
|
||||
_ = make(T, 10, 20)
|
||||
|
|
|
@ -144,7 +144,7 @@ func close1() {
|
|||
var r <-chan int
|
||||
close() // ERROR not enough 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(c)
|
||||
_ = close /* ERROR used as value */ (c)
|
||||
|
|
|
@ -105,8 +105,6 @@ func asPointer(t Type) *Pointer {
|
|||
return op
|
||||
}
|
||||
|
||||
// asTuple is not needed - not provided
|
||||
|
||||
func asSignature(t Type) *Signature {
|
||||
op, _ := optype(t).(*Signature)
|
||||
return op
|
||||
|
@ -117,11 +115,6 @@ func asMap(t Type) *Map {
|
|||
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
|
||||
// (possibly after expanding an instance type), these methods return that type.
|
||||
// Otherwise the result is nil.
|
||||
|
|
|
@ -66,5 +66,5 @@ func main() {
|
|||
close(c)
|
||||
close(cs)
|
||||
close(cr) // ERROR "receive"
|
||||
close(n) // ERROR "invalid operation.*non-chan type|must be channel|not a channel"
|
||||
close(n) // ERROR "invalid operation.*non-chan type|must be channel|non-channel"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue