mirror of
https://github.com/golang/go.git
synced 2024-09-21 10:28:27 +00:00
go/types: use combined type and ordinary args for type inference
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>
This commit is contained in:
parent
ad989c7dba
commit
1e235cd454
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -16,5 +16,9 @@ func f[V interface{}, A, B Box[V]]() {}
|
||||
|
||||
func _() {
|
||||
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.
|
||||
// TODO(rFindley) Reconcile this error position with types2.
|
||||
f /* ERROR does not satisfy Box */ [int, Optional[int], Optional[string]]()
|
||||
}
|
||||
|
20
src/go/types/fixedbugs/issue44799.go2
Normal file
20
src/go/types/fixedbugs/issue44799.go2
Normal file
@ -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)
|
||||
}
|
||||
|
5
src/go/types/testdata/issues.go2
vendored
5
src/go/types/testdata/issues.go2
vendored
@ -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]()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user