1
0
mirror of https://github.com/golang/go synced 2024-11-23 07:40:04 -07:00

go/types, types2: use correct parameter list when checking argument passing

The existing code was simply wrong: we cannot ever use the result
signature parameter list (rsig.params) if sigParams was adjusted
for variadic functions. If it was adjusted, we always must either
use sigParams or its separately instantiated version.

In the condition "n > 0 && adjusted", the "n > 0" should have
been in either of the respective "if statement" branches.

Simplified the code by merging with the result signature parameter
update.

Fixes #61931.

Change-Id: I5d39bc8bbc4dd85c7c985055d29532b4b176955e
Reviewed-on: https://go-review.googlesource.com/c/go/+/519456
Auto-Submit: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2023-08-14 15:56:08 -07:00 committed by Gopher Robot
parent 3be2176d92
commit f2f5979253
4 changed files with 60 additions and 24 deletions

View File

@ -610,21 +610,18 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T
return // error already reported return // error already reported
} }
// compute result signature: instantiate if needed // update result signature: instantiate if needed
rsig = sig
if n > 0 { if n > 0 {
rsig = check.instantiateSignature(call.Pos(), call.Fun, sig, targs[:n], xlist) rsig = check.instantiateSignature(call.Pos(), call.Fun, sig, targs[:n], xlist)
} // If the callee's parameter list was adjusted we need to update (instantiate)
// it separately. Otherwise we can simply use the result signature's parameter
// Optimization: Only if the callee's parameter list was adjusted do we need to // list.
// compute it from the adjusted list; otherwise we can simply use the result if adjusted {
// signature's parameter list. We only need the n type parameters and arguments
// of the callee.
if n > 0 && adjusted {
sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(tparams[:n], targs[:n]), nil, check.context()).(*Tuple) sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(tparams[:n], targs[:n]), nil, check.context()).(*Tuple)
} else { } else {
sigParams = rsig.params sigParams = rsig.params
} }
}
// compute argument signatures: instantiate if needed // compute argument signatures: instantiate if needed
j := n j := n

View File

@ -900,3 +900,23 @@ func _cgoCheckResult(interface{})
*boolFieldAddr(cfg, "go115UsesCgo") = true *boolFieldAddr(cfg, "go115UsesCgo") = true
}) })
} }
func TestIssue61931(t *testing.T) {
const src = `
package p
func A(func(any), ...any) {}
func B[T any](T) {}
func _() {
A(B, nil // syntax error: missing ',' before newline in argument list
}
`
f, err := syntax.Parse(syntax.NewFileBase(pkgName(src)), strings.NewReader(src), func(error) {}, nil, 0)
if err == nil {
t.Fatal("expected syntax error")
}
var conf Config
conf.Check(f.PkgName.Value, []*syntax.File{f}, nil) // must not panic
}

View File

@ -612,21 +612,18 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type
return // error already reported return // error already reported
} }
// compute result signature: instantiate if needed // update result signature: instantiate if needed
rsig = sig
if n > 0 { if n > 0 {
rsig = check.instantiateSignature(call.Pos(), call.Fun, sig, targs[:n], xlist) rsig = check.instantiateSignature(call.Pos(), call.Fun, sig, targs[:n], xlist)
} // If the callee's parameter list was adjusted we need to update (instantiate)
// it separately. Otherwise we can simply use the result signature's parameter
// Optimization: Only if the callee's parameter list was adjusted do we need to // list.
// compute it from the adjusted list; otherwise we can simply use the result if adjusted {
// signature's parameter list. We only need the n type parameters and arguments
// of the callee.
if n > 0 && adjusted {
sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(tparams[:n], targs[:n]), nil, check.context()).(*Tuple) sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(tparams[:n], targs[:n]), nil, check.context()).(*Tuple)
} else { } else {
sigParams = rsig.params sigParams = rsig.params
} }
}
// compute argument signatures: instantiate if needed // compute argument signatures: instantiate if needed
j := n j := n

View File

@ -10,6 +10,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"go/importer" "go/importer"
"go/parser"
"go/token" "go/token"
"internal/testenv" "internal/testenv"
"regexp" "regexp"
@ -908,3 +909,24 @@ func _cgoCheckResult(interface{})
*boolFieldAddr(cfg, "go115UsesCgo") = true *boolFieldAddr(cfg, "go115UsesCgo") = true
}) })
} }
func TestIssue61931(t *testing.T) {
const src = `
package p
func A(func(any), ...any) {}
func B[T any](T) {}
func _() {
A(B, nil // syntax error: missing ',' before newline in argument list
}
`
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, pkgName(src), src, 0)
if err == nil {
t.Fatal("expected syntax error")
}
var conf Config
conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // must not panic
}