import (
"cmd/compile/internal/syntax"
- "fmt"
. "internal/types/errors"
"strings"
"unicode"
return targs, xlist
}
- // If the uninstantiated or partially instantiated function x is used in an
- // assignment (tsig != nil), use the respective function parameter and result
- // types to infer additional type arguments.
+ // If the uninstantiated or partially instantiated function x is used in
+ // an assignment (tsig != nil), infer missing type arguments by treating
+ // the assignment
+ //
+ // var tvar tsig = x
+ //
+ // like a call g(tvar) of the synthetic generic function g
+ //
+ // func g[type_parameters_of_x](func_type_of_x)
+ //
var args []*operand
var params []*Var
- if tsig != nil && sig.tparams != nil && tsig.params.Len() == sig.params.Len() && tsig.results.Len() == sig.results.Len() {
- // x is a generic function and the signature arity matches the target function.
- // To infer x's missing type arguments, treat the function assignment as a call
- // of a synthetic function f where f's parameters are the parameters and results
- // of x and where the arguments to the call of f are values of the parameter and
- // result types of x.
+ if tsig != nil && sig.tparams != nil {
if !versionErr && !check.allowVersion(check.pkg, instErrPos, go1_21) {
if inst != nil {
check.versionErrorf(instErrPos, go1_21, "partially instantiated function in assignment")
check.versionErrorf(instErrPos, go1_21, "implicitly instantiated function in assignment")
}
}
- n := tsig.params.Len()
- m := tsig.results.Len()
- args = make([]*operand, n+m)
- params = make([]*Var, n+m)
- for i := 0; i < n; i++ {
- lvar := tsig.params.At(i)
- lname := syntax.NewName(x.Pos(), paramName(lvar.name, i, "parameter"))
- args[i] = &operand{mode: value, expr: lname, typ: lvar.typ}
- params[i] = sig.params.At(i)
- }
- for i := 0; i < m; i++ {
- lvar := tsig.results.At(i)
- lname := syntax.NewName(x.Pos(), paramName(lvar.name, i, "result parameter"))
- args[n+i] = &operand{mode: value, expr: lname, typ: lvar.typ}
- params[n+i] = sig.results.At(i)
- }
+ gsig := NewSignatureType(nil, nil, nil, sig.params, sig.results, sig.variadic)
+ params = []*Var{NewVar(x.Pos(), check.pkg, "", gsig)}
+ // The type of the argument operand is tsig, which is the type of the LHS in an assignment
+ // or the result type in a return statement. Create a pseudo-expression for that operand
+ // that makes sense when reported in error messages from infer, below.
+ expr := syntax.NewName(x.Pos(), "variable in assignment")
+ args = []*operand{{mode: value, expr: expr, typ: tsig}}
}
// Rename type parameters to avoid problems with recursive instantiations.
return nil, nil
}
-func paramName(name string, i int, kind string) string {
- if name != "" {
- return name
- }
- return nth(i+1) + " " + kind
-}
-
-func nth(n int) string {
- switch n {
- case 1:
- return "1st"
- case 2:
- return "2nd"
- case 3:
- return "3rd"
- }
- return fmt.Sprintf("%dth", n)
-}
-
func (check *Checker) instantiateSignature(pos syntax.Pos, expr syntax.Expr, typ *Signature, targs []Type, xlist []syntax.Expr) (res *Signature) {
assert(check != nil)
assert(len(targs) == typ.TypeParams().Len())
-// Copyright 2022 The Go Authors. All rights reserved.
+// 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 types
import (
- "fmt"
"go/ast"
"go/internal/typeparams"
"go/token"
return targs, xlist
}
- // If the uninstantiated or partially instantiated function x is used in an
- // assignment (tsig != nil), use the respective function parameter and result
- // types to infer additional type arguments.
+ // If the uninstantiated or partially instantiated function x is used in
+ // an assignment (tsig != nil), infer missing type arguments by treating
+ // the assignment
+ //
+ // var tvar tsig = x
+ //
+ // like a call g(tvar) of the synthetic generic function g
+ //
+ // func g[type_parameters_of_x](func_type_of_x)
+ //
var args []*operand
var params []*Var
- if tsig != nil && sig.tparams != nil && tsig.params.Len() == sig.params.Len() && tsig.results.Len() == sig.results.Len() {
- // x is a generic function and the signature arity matches the target function.
- // To infer x's missing type arguments, treat the function assignment as a call
- // of a synthetic function f where f's parameters are the parameters and results
- // of x and where the arguments to the call of f are values of the parameter and
- // result types of x.
+ if tsig != nil && sig.tparams != nil {
if !versionErr && !check.allowVersion(check.pkg, instErrPos, go1_21) {
if ix != nil {
check.versionErrorf(instErrPos, go1_21, "partially instantiated function in assignment")
check.versionErrorf(instErrPos, go1_21, "implicitly instantiated function in assignment")
}
}
- n := tsig.params.Len()
- m := tsig.results.Len()
- args = make([]*operand, n+m)
- params = make([]*Var, n+m)
- for i := 0; i < n; i++ {
- lvar := tsig.params.At(i)
- lname := ast.NewIdent(paramName(lvar.name, i, "parameter"))
- lname.NamePos = x.Pos() // correct position
- args[i] = &operand{mode: value, expr: lname, typ: lvar.typ}
- params[i] = sig.params.At(i)
- }
- for i := 0; i < m; i++ {
- lvar := tsig.results.At(i)
- lname := ast.NewIdent(paramName(lvar.name, i, "result parameter"))
- lname.NamePos = x.Pos() // correct position
- args[n+i] = &operand{mode: value, expr: lname, typ: lvar.typ}
- params[n+i] = sig.results.At(i)
- }
+ gsig := NewSignatureType(nil, nil, nil, sig.params, sig.results, sig.variadic)
+ params = []*Var{NewVar(x.Pos(), check.pkg, "", gsig)}
+ // The type of the argument operand is tsig, which is the type of the LHS in an assignment
+ // or the result type in a return statement. Create a pseudo-expression for that operand
+ // that makes sense when reported in error messages from infer, below.
+ expr := ast.NewIdent("variable in assignment")
+ expr.NamePos = x.Pos() // correct position
+ args = []*operand{{mode: value, expr: expr, typ: tsig}}
}
// Rename type parameters to avoid problems with recursive instantiations.
return nil, nil
}
-func paramName(name string, i int, kind string) string {
- if name != "" {
- return name
- }
- return nth(i+1) + " " + kind
-}
-
-func nth(n int) string {
- switch n {
- case 1:
- return "1st"
- case 2:
- return "2nd"
- case 3:
- return "3rd"
- }
- return fmt.Sprintf("%dth", n)
-}
-
func (check *Checker) instantiateSignature(pos token.Pos, expr ast.Expr, typ *Signature, targs []Type, xlist []ast.Expr) (res *Signature) {
assert(check != nil)
assert(len(targs) == typ.TypeParams().Len())
-// Copyright 2022 The Go Authors. All rights reserved.
+// 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.
_ func(int) int = f3[int]
v6 func(int, int) = f4
- v7 func(int, string) = f4 // ERROR "type string of 2nd parameter does not match inferred type int for P"
+ v7 func(int, string) = f4 // ERROR "type func(int, string) of variable in assignment does not match inferred type func(int, int) for func(P, P)"
v8 func(int) []int = f5
- v9 func(string) []int = f5 // ERROR "type []int of 1st result parameter does not match inferred type []string for []P"
+ v9 func(string) []int = f5 // ERROR "type func(string) []int of variable in assignment does not match inferred type func(string) []string for func(P) []P"
_, _ func(int) = f1, f1
_, _ func(int) = f1, f2 // ERROR "cannot infer P"
v5 = f3[int]
v6 = f4
- v7 = f4 // ERROR "type string of 2nd parameter does not match inferred type int for P"
+ v7 = f4 // ERROR "type func(int, string) of variable in assignment does not match inferred type func(int, int) for func(P, P)"
v8 = f5
- v9 = f5 // ERROR "type []int of 1st result parameter does not match inferred type []string for []P"
+ v9 = f5 // ERROR "type func(string) []int of variable in assignment does not match inferred type func(string) []string for func(P) []P"
}
// Return statements
func _() func(int, int) { return f4 }
func _() func(int, string) {
- return f4 /* ERROR "type string of 2nd parameter does not match inferred type int for P" */
+ return f4 /* ERROR "type func(int, string) of variable in assignment does not match inferred type func(int, int) for func(P, P)" */
}
func _() func(int) []int { return f5 }
func _() func(string) []int {
- return f5 /* ERROR "type []int of 1st result parameter does not match inferred type []string for []P" */
+ return f5 /* ERROR "type func(string) []int of variable in assignment does not match inferred type func(string) []string for func(P) []P" */
}
func _() (_, _ func(int)) { return f1, f1 }
--- /dev/null
+// 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
+
+type String string
+
+func g[P any](P, string) {}
+
+// String and string are not identical and thus must not unify
+// (they are element types of the func type and therefore must
+// be identical to match).
+// The result is an error from type inference, rather than an
+// error from an assignment mismatch.
+var f func(int, String) = g // ERROR "type func(int, String) of variable in assignment does not match inferred type func(int, string) for func(P, string)"