]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: use combined type and ordinary args for type inference
authorRob Findley <rfindley@google.com>
Wed, 28 Apr 2021 02:52:56 +0000 (22:52 -0400)
committerRobert Findley <rfindley@google.com>
Wed, 28 Apr 2021 19:51:56 +0000 (19:51 +0000)
This is a port of CL 308372 to go/types. The only meaningful change was
to add TODOs to improve the positioning error messages.

Change-Id: I8314615d0851a59c2b5fd30eb897d581652eacc3
Reviewed-on: https://go-review.googlesource.com/c/go/+/314435
Trust: Robert Findley <rfindley@google.com>
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/types/builtins.go
src/go/types/call.go
src/go/types/fixedbugs/issue39754.go2
src/go/types/fixedbugs/issue44799.go2 [new file with mode: 0644]
src/go/types/testdata/issues.go2

index 9c5a0b5842c15ad5aa97faf47e21e1e374986b3e..739051cc611b3c68488f1c6f8f55bbc4d307a217 100644 (file)
@@ -130,7 +130,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                        arg(&x, i)
                        xlist = append(xlist, &x)
                }
-               check.arguments(call, sig, xlist) // discard result (we know the result type)
+               check.arguments(call, sig, nil, xlist) // discard result (we know the result type)
                // ok to continue even if check.arguments reported errors
 
                x.mode = value
index e23bdb830d6b89d1c909ec18086d751f7aab43ec..631ea426c6bbf42e5fe613e4936942a2e253d055 100644 (file)
@@ -72,9 +72,14 @@ func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) {
 }
 
 func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
+       var inst *ast.IndexExpr
        if iexpr, _ := call.Fun.(*ast.IndexExpr); iexpr != nil {
                if check.indexExpr(x, iexpr) {
-                       check.funcInst(x, iexpr)
+                       // Delay function instantiation to argument checking,
+                       // where we combine type and value arguments for type
+                       // inference.
+                       assert(x.mode == value)
+                       inst = iexpr
                }
                x.expr = iexpr
                check.record(x)
@@ -142,9 +147,33 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
                return statement
        }
 
+       // evaluate type arguments, if any
+       var targs []Type
+       if inst != nil {
+               xlist := typeparams.UnpackExpr(inst.Index)
+               targs = check.typeList(xlist)
+               if targs == nil {
+                       check.use(call.Args...)
+                       x.mode = invalid
+                       x.expr = call
+                       return statement
+               }
+               assert(len(targs) == len(xlist))
+
+               // check number of type arguments (got) vs number of type parameters (want)
+               got, want := len(targs), len(sig.tparams)
+               if got > want {
+                       check.errorf(xlist[want], _Todo, "got %d type arguments but want %d", got, want)
+                       check.use(call.Args...)
+                       x.mode = invalid
+                       x.expr = call
+                       return statement
+               }
+       }
+
        // evaluate arguments
        args, _ := check.exprList(call.Args, false)
-       sig = check.arguments(call, sig, args)
+       sig = check.arguments(call, sig, targs, args)
 
        // determine result
        switch sig.results.Len() {
@@ -217,7 +246,7 @@ func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*op
        return
 }
 
-func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, args []*operand) (rsig *Signature) {
+func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, args []*operand) (rsig *Signature) {
        rsig = sig
 
        // TODO(gri) try to eliminate this extra verification loop
@@ -299,7 +328,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, args []*oper
        if len(sig.tparams) > 0 {
                // TODO(gri) provide position information for targs so we can feed
                //           it to the instantiate call for better error reporting
-               targs := check.infer(call, sig.tparams, nil, sigParams, args, true)
+               targs := check.infer(call, sig.tparams, targs, sigParams, args, true)
                if targs == nil {
                        return // error already reported
                }
index 2ed84dc8abed9b0d0a0e6e2bedcdf3d0c0763692..4b4420d9973aaf5e579d98016e181023f0b25325 100644 (file)
@@ -16,5 +16,9 @@ func f[V interface{}, A, B Box[V]]() {}
 \r
 func _() {\r
        f[int, Optional[int], Optional[int]]()\r
-       // f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]()\r
+       _ = f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]\r
+       // TODO(gri) Provide better position information here.\r
+       //           See TODO in call.go, Checker.arguments.\r
+       // TODO(rFindley) Reconcile this error position with types2.\r
+       f /* ERROR does not satisfy Box */ [int, Optional[int], Optional[string]]()\r
 }\r
diff --git a/src/go/types/fixedbugs/issue44799.go2 b/src/go/types/fixedbugs/issue44799.go2
new file mode 100644 (file)
index 0000000..33f2c9a
--- /dev/null
@@ -0,0 +1,20 @@
+// 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 main
+
+func Map[F, T any](s []F, f func(F) T) []T { return nil }
+
+func Reduce[Elem1, Elem2 any](s []Elem1, initializer Elem2, f func(Elem2, Elem1) Elem2) Elem2 { var x Elem2; return x }
+
+func main() {
+       var s []int
+       var f1 func(int) float64
+       var f2 func(float64, int) float64
+       _ = Map[int](s, f1)
+       _ = Map(s, f1)
+       _ = Reduce[int](s, 0, f2)
+       _ = Reduce(s, 0, f2)
+}
+
index 2d4bb32c4b3451cbbe0ea18a36c3c03db99590ed..8994164eacf5f9cd4bf2838b2b47442c2bc3ae6e 100644 (file)
@@ -26,7 +26,7 @@ func _() {
 
 // If we have a receiver of pointer type (below: *T) we must ignore
 // the pointer in the implementation of the method lookup because
-// the type bound of T is an interface an pointer to interface types
+// the type bound of T is an interface and pointer to interface types
 // have no methods and then the lookup would fail.
 type C[T any] interface {
     m()
@@ -55,7 +55,8 @@ func (T) m1()
 func (*T) m2()
 
 func _() {
-       f2[T /* ERROR wrong method signature */]()
+       // TODO(rFindley) this error should be positioned on the 'T'.
+       f2 /* ERROR wrong method signature */ [T]()
        f2[*T]()
 }