diff --git a/src/go/types/examples/contracts.go2 b/src/go/types/examples/contracts.go2 index f82b4a0074..01372a15d3 100644 --- a/src/go/types/examples/contracts.go2 +++ b/src/go/types/examples/contracts.go2 @@ -35,7 +35,7 @@ contract Sequence(T) { } // Contracts may not be declared locally. They are accepted -// for good syntax error recovery, but an errors are reported. +// for good syntax error recovery, but errors are reported. func _() { contract /* ERROR "inside function" */ C() {} contract /* ERROR "inside function" */ C(T) {} diff --git a/src/go/types/examples/functions.go2 b/src/go/types/examples/functions.go2 index 3cd0a0c43f..15297d42ae 100644 --- a/src/go/types/examples/functions.go2 +++ b/src/go/types/examples/functions.go2 @@ -111,3 +111,53 @@ func max(type T interface{ type int })(x ...T) T { } return x0 } + +// When inferring channel types, the channel direction is ignored +// for the purpose of type inference. Once the type has been in- +// fered, the usual parameter passing rules are applied. +// Thus even if a type can be inferred successfully, the function +// call may not be valid. + +func fboth(type T)(chan T) +func frecv(type T)(<-chan T) +func fsend(type T)(chan<- T) + +func _() { + var both chan int + var recv <-chan int + var send chan<-int + + fboth(both) + fboth(recv /* ERROR cannot use */ ) + fboth(send /* ERROR cannot use */ ) + + frecv(both) + frecv(recv) + frecv(send /* ERROR cannot use */ ) + + fsend(both) + fsend(recv /* ERROR cannot use */) + fsend(send) +} + +func ffboth(type T)(func(chan T)) +func ffrecv(type T)(func(<-chan T)) +func ffsend(type T)(func(chan<- T)) + +func _() { + var both func(chan int) + var recv func(<-chan int) + var send func(chan<- int) + + ffboth(both) + ffboth(recv /* ERROR cannot use */ ) + ffboth(send /* ERROR cannot use */ ) + + ffrecv(both /* ERROR cannot use */ ) + ffrecv(recv) + ffrecv(send /* ERROR cannot use */ ) + + ffsend(both /* ERROR cannot use */ ) + ffsend(recv /* ERROR cannot use */ ) + ffsend(send) +} diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 3c47ae8d0c..eb919b06bd 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -289,9 +289,9 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair, tparams case *Chan: // Two channel types are identical if they have identical value types - // and the same direction. + // and the same direction. For type inference, channel direction is ignored. if y, ok := y.(*Chan); ok { - return x.dir == y.dir && check.identical0(x.elem, y.elem, cmpTags, p, tparams) + return (tparams != nil || x.dir == y.dir) && check.identical0(x.elem, y.elem, cmpTags, p, tparams) } case *Named: diff --git a/src/go/types/testdata/tmp.go2 b/src/go/types/testdata/tmp.go2 index ff68694fd7..28916cc839 100644 --- a/src/go/types/testdata/tmp.go2 +++ b/src/go/types/testdata/tmp.go2 @@ -2,23 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package main - -func f(type T)(x T) { - f(x) -} - -func g(type T)(x, y T) { - g(x, y) -} - -func f2(type T1, T2)(x1 T1, x2 T2) { - f2(x1, x2) -} - -func f2p(type T1, T2)(x1 T1, x2 T2) { - f2p(x2, x1) -} +package p /* func f(func(int))