aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/types2/call.go38
-rw-r--r--src/cmd/compile/internal/types2/expr.go4
-rw-r--r--src/go/types/call.go38
-rw-r--r--src/go/types/expr.go4
4 files changed, 60 insertions, 24 deletions
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index 23738e2aac..54f6c7ee48 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -14,13 +14,26 @@ import (
"unicode"
)
-// funcInst type-checks a function instantiation and returns the result in x.
-// The incoming x must be an uninstantiated generic function. If inst != nil,
-// it provides (some or all of) the type arguments (inst.Index) for the
-// instantiation. If the target type tsig != nil, the signature's parameter
-// types are used to infer additional missing type arguments of x, if any.
-// At least one of tsig or inst must be provided.
-func (check *Checker) funcInst(tsig *Signature, pos syntax.Pos, x *operand, inst *syntax.IndexExpr) {
+// funcInst type-checks a function instantiation.
+// The incoming x must be a generic function.
+// If inst != nil, it provides some or all of the type arguments (inst.Index).
+// If target type tsig != nil, the signature may be used to infer missing type
+// arguments of x, if any. At least one of tsig or inst must be provided.
+//
+// There are two modes of operation:
+//
+// 1. If infer == true, funcInst infers missing type arguments as needed and
+// instantiates the function x. The returned results are nil.
+//
+// 2. If infer == false and inst provides all type arguments, funcInst
+// instantiates the function x. The returned results are nil.
+// If inst doesn't provide enough type arguments, funcInst returns the
+// available arguments and the corresponding expression list; x remains
+// unchanged.
+//
+// If an error (other than a version error) occurs in any case, it is reported
+// and x.mode is set to invalid.
+func (check *Checker) funcInst(tsig *Signature, pos syntax.Pos, x *operand, inst *syntax.IndexExpr, infer bool) ([]Type, []syntax.Expr) {
assert(tsig != nil || inst != nil)
var instErrPos poser
@@ -40,7 +53,7 @@ func (check *Checker) funcInst(tsig *Signature, pos syntax.Pos, x *operand, inst
if targs == nil {
x.mode = invalid
x.expr = inst
- return
+ return nil, nil
}
assert(len(targs) == len(xlist))
}
@@ -55,10 +68,14 @@ func (check *Checker) funcInst(tsig *Signature, pos syntax.Pos, x *operand, inst
check.errorf(xlist[got-1], WrongTypeArgCount, "got %d type arguments but want %d", got, want)
x.mode = invalid
x.expr = inst
- return
+ return nil, nil
}
if got < want {
+ if !infer {
+ 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.
@@ -104,7 +121,7 @@ func (check *Checker) funcInst(tsig *Signature, pos syntax.Pos, x *operand, inst
// error was already reported
x.mode = invalid
x.expr = inst
- return
+ return nil, nil
}
got = len(targs)
}
@@ -121,6 +138,7 @@ func (check *Checker) funcInst(tsig *Signature, pos syntax.Pos, x *operand, inst
x.expr = inst
}
check.recordInstance(x.expr, targs, sig)
+ return nil, nil
}
func paramName(name string, i int, kind string) string {
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 0f473293bc..e69f2e4c10 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -995,7 +995,7 @@ func (check *Checker) nonGeneric(T Type, x *operand) {
if t.tparams != nil {
if enableReverseTypeInference && T != nil {
if tsig, _ := under(T).(*Signature); tsig != nil {
- check.funcInst(tsig, x.Pos(), x, nil)
+ check.funcInst(tsig, x.Pos(), x, nil, true)
return
}
}
@@ -1322,7 +1322,7 @@ func (check *Checker) exprInternal(T Type, x *operand, e syntax.Expr, hint Type)
if enableReverseTypeInference && T != nil {
tsig, _ = under(T).(*Signature)
}
- check.funcInst(tsig, e.Pos(), x, e)
+ check.funcInst(tsig, e.Pos(), x, e, true)
}
if x.mode == invalid {
goto Error
diff --git a/src/go/types/call.go b/src/go/types/call.go
index f2ff4cf857..5877a345df 100644
--- a/src/go/types/call.go
+++ b/src/go/types/call.go
@@ -16,13 +16,26 @@ import (
"unicode"
)
-// funcInst type-checks a function instantiation and returns the result in x.
-// The incoming x must be an uninstantiated generic function. If ix != nil,
-// it provides (some or all of) the type arguments (ix.Indices) for the
-// instantiation. If the target type tsig != nil, the signature's parameter
-// types are used to infer additional missing type arguments of x, if any.
-// At least one of tsig or ix must be provided.
-func (check *Checker) funcInst(tsig *Signature, pos token.Pos, x *operand, ix *typeparams.IndexExpr) {
+// funcInst type-checks a function instantiation.
+// The incoming x must be a generic function.
+// If ix != nil, it provides some or all of the type arguments (ix.Indices).
+// If target type tsig != nil, the signature may be used to infer missing type
+// arguments of x, if any. At least one of tsig or inst must be provided.
+//
+// There are two modes of operation:
+//
+// 1. If infer == true, funcInst infers missing type arguments as needed and
+// instantiates the function x. The returned results are nil.
+//
+// 2. If infer == false and inst provides all type arguments, funcInst
+// instantiates the function x. The returned results are nil.
+// If inst doesn't provide enough type arguments, funcInst returns the
+// available arguments and the corresponding expression list; x remains
+// unchanged.
+//
+// If an error (other than a version error) occurs in any case, it is reported
+// and x.mode is set to invalid.
+func (check *Checker) funcInst(tsig *Signature, pos token.Pos, x *operand, ix *typeparams.IndexExpr, infer bool) ([]Type, []ast.Expr) {
assert(tsig != nil || ix != nil)
var instErrPos positioner
@@ -42,7 +55,7 @@ func (check *Checker) funcInst(tsig *Signature, pos token.Pos, x *operand, ix *t
if targs == nil {
x.mode = invalid
x.expr = ix
- return
+ return nil, nil
}
assert(len(targs) == len(xlist))
}
@@ -57,10 +70,14 @@ func (check *Checker) funcInst(tsig *Signature, pos token.Pos, x *operand, ix *t
check.errorf(ix.Indices[got-1], WrongTypeArgCount, "got %d type arguments but want %d", got, want)
x.mode = invalid
x.expr = ix.Orig
- return
+ return nil, nil
}
if got < want {
+ if !infer {
+ 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.
@@ -108,7 +125,7 @@ func (check *Checker) funcInst(tsig *Signature, pos token.Pos, x *operand, ix *t
// error was already reported
x.mode = invalid
x.expr = ix // TODO(gri) is this correct?
- return
+ return nil, nil
}
got = len(targs)
}
@@ -125,6 +142,7 @@ func (check *Checker) funcInst(tsig *Signature, pos token.Pos, x *operand, ix *t
x.expr = ix.Orig
}
check.recordInstance(x.expr, targs, sig)
+ return nil, nil
}
func paramName(name string, i int, kind string) string {
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index b0e1422b01..898c562785 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -980,7 +980,7 @@ func (check *Checker) nonGeneric(T Type, x *operand) {
if t.tparams != nil {
if enableReverseTypeInference && T != nil {
if tsig, _ := under(T).(*Signature); tsig != nil {
- check.funcInst(tsig, x.Pos(), x, nil)
+ check.funcInst(tsig, x.Pos(), x, nil, true)
return
}
}
@@ -1305,7 +1305,7 @@ func (check *Checker) exprInternal(T Type, x *operand, e ast.Expr, hint Type) ex
if enableReverseTypeInference && T != nil {
tsig, _ = under(T).(*Signature)
}
- check.funcInst(tsig, e.Pos(), x, ix)
+ check.funcInst(tsig, e.Pos(), x, ix, true)
}
if x.mode == invalid {
goto Error