mirror of
https://github.com/golang/go
synced 2024-11-26 16:57:14 -07:00
cmd/compile/internal/types2: use combined type and ordinary args for type inference
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>
This commit is contained in:
parent
a6d95b4508
commit
3f4977bd58
@ -129,7 +129,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||||||
arg(&x, i)
|
arg(&x, i)
|
||||||
xlist = append(xlist, &x)
|
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
|
// ok to continue even if check.arguments reported errors
|
||||||
|
|
||||||
x.mode = value
|
x.mode = value
|
||||||
|
@ -67,9 +67,14 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
|
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 iexpr, _ := call.Fun.(*syntax.IndexExpr); iexpr != nil {
|
||||||
if check.indexExpr(x, iexpr) {
|
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
|
x.expr = iexpr
|
||||||
check.record(x)
|
check.record(x)
|
||||||
@ -137,9 +142,33 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
|
|||||||
return statement
|
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
|
// evaluate arguments
|
||||||
args, _ := check.exprList(call.ArgList, false)
|
args, _ := check.exprList(call.ArgList, false)
|
||||||
sig = check.arguments(call, sig, args)
|
sig = check.arguments(call, sig, targs, args)
|
||||||
|
|
||||||
// determine result
|
// determine result
|
||||||
switch sig.results.Len() {
|
switch sig.results.Len() {
|
||||||
@ -208,7 +237,7 @@ func (check *Checker) exprList(elist []syntax.Expr, allowCommaOk bool) (xlist []
|
|||||||
return
|
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
|
rsig = sig
|
||||||
|
|
||||||
// TODO(gri) try to eliminate this extra verification loop
|
// 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 {
|
if len(sig.tparams) > 0 {
|
||||||
// TODO(gri) provide position information for targs so we can feed
|
// TODO(gri) provide position information for targs so we can feed
|
||||||
// it to the instantiate call for better error reporting
|
// 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 {
|
if targs == nil {
|
||||||
return // error already reported
|
return // error already reported
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// UNREVIEWED
|
|
||||||
// Copyright 2020 The Go Authors. All rights reserved.
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
@ -17,5 +16,8 @@ func f[V interface{}, A, B Box[V]]() {}
|
|||||||
|
|
||||||
func _() {
|
func _() {
|
||||||
f[int, Optional[int], Optional[int]]()
|
f[int, Optional[int], Optional[int]]()
|
||||||
f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]()
|
_ = f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]
|
||||||
|
// TODO(gri) Provide better position information here.
|
||||||
|
// See TODO in call.go, Checker.arguments.
|
||||||
|
f[int, Optional[int], Optional[string]]( /* ERROR does not satisfy Box */ )
|
||||||
}
|
}
|
||||||
|
19
src/cmd/compile/internal/types2/fixedbugs/issue44799.go2
Normal file
19
src/cmd/compile/internal/types2/fixedbugs/issue44799.go2
Normal file
@ -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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user