go/types: ignore channel directions for type inference

Change-Id: Ic7c61dfea7b43bb102bff077bf17d86b26fffba9
This commit is contained in:
Robert Griesemer 2020-03-18 15:32:12 -07:00
parent db2cf1336d
commit e490a1bfb5
4 changed files with 54 additions and 20 deletions

View File

@ -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) {}

View File

@ -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)
}

View File

@ -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:

View File

@ -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))