]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: use combined type and ordinary args for type inference
authorRobert Griesemer <gri@golang.org>
Thu, 8 Apr 2021 05:36:15 +0000 (22:36 -0700)
committerRobert Griesemer <gri@golang.org>
Sat, 10 Apr 2021 19:02:08 +0000 (19:02 +0000)
Fixes #44799.

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

index f0fd216b1350b7ba7af037bf5bd6ee3393fd6845..25bfb24ef47199281a2e3502fa6c8154bee08238 100644 (file)
@@ -129,7 +129,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                        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 b340c52e7462ed30e8d3b8efb7ec1e013556ec82..6d149340b285b3e6bd8fc241e7dd5a50a8036370 100644 (file)
@@ -67,9 +67,14 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) {
 }
 
 func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
+       var inst *syntax.IndexExpr // function instantiation, if any
        if iexpr, _ := call.Fun.(*syntax.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)
@@ -137,9 +142,33 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
                return statement
        }
 
+       // evaluate type arguments, if any
+       var targs []Type
+       if inst != nil {
+               xlist := unpackExpr(inst.Index)
+               targs = check.typeList(xlist)
+               if targs == nil {
+                       check.use(call.ArgList...)
+                       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], "got %d type arguments but want %d", got, want)
+                       check.use(call.ArgList...)
+                       x.mode = invalid
+                       x.expr = call
+                       return statement
+               }
+       }
+
        // evaluate arguments
        args, _ := check.exprList(call.ArgList, false)
-       sig = check.arguments(call, sig, args)
+       sig = check.arguments(call, sig, targs, args)
 
        // determine result
        switch sig.results.Len() {
@@ -208,7 +237,7 @@ func (check *Checker) exprList(elist []syntax.Expr, allowCommaOk bool) (xlist []
        return
 }
 
-func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, args []*operand) (rsig *Signature) {
+func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []Type, args []*operand) (rsig *Signature) {
        rsig = sig
 
        // TODO(gri) try to eliminate this extra verification loop
@@ -292,7 +321,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, args []*o
        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.Pos(), sig.tparams, nil, sigParams, args, true)
+               targs = check.infer(call.Pos(), sig.tparams, targs, sigParams, args, true)
                if targs == nil {
                        return // error already reported
                }
index 36b774faaf0769264c85a96f51155e47e6b6f76f..f70b8d0ce0388757004f3797bac5cae749429177 100644 (file)
@@ -1,4 +1,3 @@
-// UNREVIEWED
 // Copyright 2020 The Go Authors. All rights reserved.\r
 // Use of this source code is governed by a BSD-style\r
 // license that can be found in the LICENSE file.\r
@@ -17,5 +16,8 @@ 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
+       f[int, Optional[int], Optional[string]]( /* ERROR does not satisfy Box */ )\r
 }\r
diff --git a/src/cmd/compile/internal/types2/fixedbugs/issue44799.go2 b/src/cmd/compile/internal/types2/fixedbugs/issue44799.go2
new file mode 100644 (file)
index 0000000..9e528a7
--- /dev/null
@@ -0,0 +1,19 @@
+// 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)
+}