| // Copyright 2023 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package p |
| |
| func f[T any](...T) T { var x T; return x } |
| |
| // Test case 1 |
| |
| func _() { |
| var a chan string |
| var b <-chan string |
| f(a, b) |
| f(b, a) |
| } |
| |
| // Test case 2 |
| |
| type F[T any] func(T) bool |
| |
| func g[T any](T) F[<-chan T] { return nil } |
| |
| func f1[T any](T, F[T]) {} |
| func f2[T any](F[T], T) {} |
| |
| func _() { |
| var ch chan string |
| f1(ch, g("")) |
| f2(g(""), ch) |
| } |
| |
| // Test case 3: named and directional types combined |
| |
| func _() { |
| type namedA chan int |
| type namedB chan<- int |
| |
| var a chan int |
| var A namedA |
| var b chan<- int |
| var B namedB |
| |
| // Defined types win over channel types irrespective of channel direction. |
| f(A, b /* ERROR "cannot use b (variable of type chan<- int) as namedA value in argument to f" */) |
| f(b /* ERROR "cannot use b (variable of type chan<- int) as namedA value in argument to f" */, A) |
| |
| f(a, b /* ERROR "cannot use b (variable of type chan<- int) as namedA value in argument to f" */, A) |
| f(a, A, b /* ERROR "cannot use b (variable of type chan<- int) as namedA value in argument to f" */) |
| f(b /* ERROR "cannot use b (variable of type chan<- int) as namedA value in argument to f" */, A, a) |
| f(b /* ERROR "cannot use b (variable of type chan<- int) as namedA value in argument to f" */, a, A) |
| f(A, a, b /* ERROR "cannot use b (variable of type chan<- int) as namedA value in argument to f" */) |
| f(A, b /* ERROR "cannot use b (variable of type chan<- int) as namedA value in argument to f" */, a) |
| |
| // Unnamed directed channels win over bidirectional channels. |
| b = f(a, b) |
| b = f(b, a) |
| |
| // Defined directed channels win over defined bidirectional channels. |
| A = f(A, a) |
| A = f(a, A) |
| B = f(B, b) |
| B = f(b, B) |
| |
| f(a, b, B) |
| f(a, B, b) |
| f(b, B, a) |
| f(b, a, B) |
| f(B, a, b) |
| f(B, b, a) |
| |
| // Differently named channel types conflict irrespective of channel direction. |
| f(A, B /* ERROR "type namedB of B does not match inferred type namedA for T" */) |
| f(B, A /* ERROR "type namedA of A does not match inferred type namedB for T" */) |
| |
| // Ensure that all combinations of directional and |
| // bidirectional channels with a named directional |
| // channel lead to the correct (named) directional |
| // channel. |
| B = f(a, b) |
| B = f(a, B) |
| B = f(b, a) |
| B = f(B, a) |
| |
| B = f(a, b, B) |
| B = f(a, B, b) |
| B = f(b, B, a) |
| B = f(b, a, B) |
| B = f(B, a, b) |
| B = f(B, b, a) |
| |
| // verify type error |
| A = f /* ERROR "cannot use f(B, b, a) (value of type namedB) as namedA value in assignment" */ (B, b, a) |
| } |
| |
| // Test case 4: some more combinations |
| |
| func _() { |
| type A chan int |
| type B chan int |
| type C = chan int |
| type D = chan<- int |
| |
| var a A |
| var b B |
| var c C |
| var d D |
| |
| f(a, b /* ERROR "type B of b does not match inferred type A for T" */, c) |
| f(c, a, b /* ERROR "type B of b does not match inferred type A for T" */) |
| f(a, b /* ERROR "type B of b does not match inferred type A for T" */, d) |
| f(d, a, b /* ERROR "type B of b does not match inferred type A for T" */) |
| } |
| |
| // Simplified test case from issue |
| |
| type Matcher[T any] func(T) bool |
| |
| func Produces[T any](T) Matcher[<-chan T] { return nil } |
| |
| func Assert1[T any](Matcher[T], T) {} |
| func Assert2[T any](T, Matcher[T]) {} |
| |
| func _() { |
| var ch chan string |
| Assert1(Produces(""), ch) |
| Assert2(ch, Produces("")) |
| } |