}
}
- // common case: if we don't have type parameters, we're done
+ // optimization: if we don't have type parameters, we're done
if Vp == nil && Tp == nil {
return false, _IncompatibleAssign
}
- // determine type parameter operands with specific type terms
- if Vp != nil && !Vp.hasTerms() {
- Vp = nil
- }
- if Tp != nil && !Tp.hasTerms() {
- Tp = nil
- }
-
errorf := func(format string, args ...interface{}) {
if check != nil && reason != nil {
msg := check.sprintf(format, args...)
}
}
- ok := false
- code := _IncompatibleAssign
- switch {
- case Vp != nil && Tp != nil:
- x := *x // don't clobber outer x
- ok = Vp.is(func(V *term) bool {
- x.typ = V.typ
- return Tp.is(func(T *term) bool {
- ok, code = x.assignableTo(check, T.typ, reason)
- if !ok {
- errorf("cannot assign %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp)
- return false
- }
- return true
- })
- })
- case Vp != nil:
- x := *x // don't clobber outer x
- ok = Vp.is(func(V *term) bool {
- x.typ = V.typ
- ok, code = x.assignableTo(check, T, reason)
+ // x's type V is not a named type and T is a type parameter, and
+ // x is assignable to each specific type in T's type set.
+ if !hasName(V) && Tp != nil {
+ ok := false
+ code := _IncompatibleAssign
+ Tp.is(func(T *term) bool {
+ if T == nil {
+ return false // no specific types
+ }
+ ok, code = x.assignableTo(check, T.typ, reason)
if !ok {
- errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T)
+ errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
return false
}
return true
})
- case Tp != nil:
+ return ok, code
+ }
+
+ // x's type V is a type parameter and T is not a named type,
+ // and values x' of each specific type in V's type set are
+ // assignable to T.
+ if Vp != nil && !hasName(T) {
x := *x // don't clobber outer x
- ok = Tp.is(func(T *term) bool {
- ok, code = x.assignableTo(check, T.typ, reason)
+ ok := false
+ code := _IncompatibleAssign
+ Vp.is(func(V *term) bool {
+ if V == nil {
+ return false // no specific types
+ }
+ x.typ = V.typ
+ ok, code = x.assignableTo(check, T, reason)
if !ok {
- errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
+ errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T)
return false
}
return true
})
+ return ok, code
}
- return ok, code
+ return false, _IncompatibleAssign
}
// kind2tok translates syntax.LitKinds into token.Tokens.
--- /dev/null
+// Copyright 2021 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 _[P int](x P) int {
+ return x // ERROR cannot use x .* as int value in return statement
+}
+
+func _[P int]() int {
+ return P /* ERROR cannot use P\(1\) .* as int value in return statement */ (1)
+}
+
+func _[P int](x int) P {
+ return x // ERROR cannot use x .* as P value in return statement
+}
+
+func _[P, Q any](x P) Q {
+ return x // ERROR cannot use x .* as Q value in return statement
+}
+
+// test case from issue
+func F[G interface{ uint }]() int {
+ f := func(uint) int { return 0 }
+ return f(G /* ERROR cannot use G\(1\) .* as uint value in argument to f */ (1))
+}
)
var (
- _ _CC = C
- _ _SC = C
- _ _RC = C
+ _ _CC = C // ERROR cannot use C .* as _CC value
+ _ _SC = C // ERROR cannot use C .* as _SC value
+ _ _RC = C // ERROR cannot use C .* as _RC value
- _ CC = _CC(nil)
- _ SC = _CC(nil)
- _ RC = _CC(nil)
+ _ CC = _CC /* ERROR cannot use _CC\(nil\) .* as CC value */ (nil)
+ _ SC = _CC /* ERROR cannot use _CC\(nil\) .* as SC value */ (nil)
+ _ RC = _CC /* ERROR cannot use _CC\(nil\) .* as RC value */ (nil)
- _ CC = C
- _ SC = C // ERROR cannot use C .* as SC value .* cannot assign Chan to SendChan
- _ RC = C // ERROR cannot use C .* as RC value .* cannot assign Chan to RecvChan
+ _ CC = C // ERROR cannot use C .* as CC value
+ _ SC = C // ERROR cannot use C .* as SC value
+ _ RC = C // ERROR cannot use C .* as RC value
)
}
+// "x's type V is not a named type and T is a type parameter, and x is assignable to each specific type in T's type set."
+func _[
+ TP0 any,
+ TP1 ~_Chan,
+ TP2 ~chan int | ~chan byte,
+]() {
+ var (
+ _ TP0 = c // ERROR cannot use c .* as TP0 value
+ _ TP0 = C // ERROR cannot use C .* as TP0 value
+ _ TP1 = c
+ _ TP1 = C // ERROR cannot use C .* as TP1 value
+ _ TP2 = c // ERROR .* cannot assign chan int to chan byte
+ )
+}
+
+// "x's type V is a type parameter and T is not a named type, and values x' of each specific type in V's type set are assignable to T."
+func _[
+ TP0 Interface,
+ TP1 ~_Chan,
+ TP2 ~chan int | ~chan byte,
+](X0 TP0, X1 TP1, X2 TP2) {
+ i = X0
+ I = X0
+ c = X1
+ C = X1 // ERROR cannot use X1 .* as Chan value
+ c = X2 // ERROR .* cannot assign chan byte \(in TP2\) to chan int
+}
+
// "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type"
func _[TP Interface](X TP) {
b = nil // ERROR cannot use untyped nil