1
0
mirror of https://github.com/golang/go synced 2024-09-29 09:24:28 -06:00

go/types, types2: explicitly look for nil type arguments in infer

Don't assume we have all type arguments if the number of type arguments
matches the number of type parameters. Instead, look explicitly for nil
type arguments in the provided targs.

Preparation for type inference with type arguments provided for type
parameters of generic function arguments passed to other functions.

For #59338.

Change-Id: I00918cd5ed06ae3277b4e41a3641063e0f53fef0
Reviewed-on: https://go-review.googlesource.com/c/go/+/494115
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Robert Griesemer 2023-05-09 14:02:07 -07:00 committed by Gopher Robot
parent 607a045888
commit d9dce0cd26
2 changed files with 26 additions and 14 deletions

View File

@ -29,10 +29,7 @@ const enableReverseTypeInference = true // disable for debugging
func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (inferred []Type) { func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (inferred []Type) {
if debug { if debug {
defer func() { defer func() {
assert(inferred == nil || len(inferred) == len(tparams)) assert(inferred == nil || len(inferred) == len(tparams) && !containsNil(inferred))
for _, targ := range inferred {
assert(targ != nil)
}
}() }()
} }
@ -47,14 +44,13 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
n := len(tparams) n := len(tparams)
assert(n > 0 && len(targs) <= n) assert(n > 0 && len(targs) <= n)
// Function parameters and arguments must match in number. // Parameters and arguments must match in number.
assert(params.Len() == len(args)) assert(params.Len() == len(args))
// If we already have all type arguments, we're done. // If we already have all type arguments, we're done.
if len(targs) == n { if len(targs) == n && !containsNil(targs) {
return targs return targs
} }
// len(targs) < n
// Make sure we have a "full" list of type arguments, some of which may // Make sure we have a "full" list of type arguments, some of which may
// be nil (unknown). Make a copy so as to not clobber the incoming slice. // be nil (unknown). Make a copy so as to not clobber the incoming slice.
@ -440,6 +436,16 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
return return
} }
// containsNil reports whether list contains a nil entry.
func containsNil(list []Type) bool {
for _, t := range list {
if t == nil {
return true
}
}
return false
}
// renameTParams renames the type parameters in the given type such that each type // renameTParams renames the type parameters in the given type such that each type
// parameter is given a new identity. renameTParams returns the new type parameters // parameter is given a new identity. renameTParams returns the new type parameters
// and updated type. If the result type is unchanged from the argument type, none // and updated type. If the result type is unchanged from the argument type, none

View File

@ -31,10 +31,7 @@ const enableReverseTypeInference = true // disable for debugging
func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (inferred []Type) { func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (inferred []Type) {
if debug { if debug {
defer func() { defer func() {
assert(inferred == nil || len(inferred) == len(tparams)) assert(inferred == nil || len(inferred) == len(tparams) && !containsNil(inferred))
for _, targ := range inferred {
assert(targ != nil)
}
}() }()
} }
@ -49,14 +46,13 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
n := len(tparams) n := len(tparams)
assert(n > 0 && len(targs) <= n) assert(n > 0 && len(targs) <= n)
// Function parameters and arguments must match in number. // Parameters and arguments must match in number.
assert(params.Len() == len(args)) assert(params.Len() == len(args))
// If we already have all type arguments, we're done. // If we already have all type arguments, we're done.
if len(targs) == n { if len(targs) == n && !containsNil(targs) {
return targs return targs
} }
// len(targs) < n
// Make sure we have a "full" list of type arguments, some of which may // Make sure we have a "full" list of type arguments, some of which may
// be nil (unknown). Make a copy so as to not clobber the incoming slice. // be nil (unknown). Make a copy so as to not clobber the incoming slice.
@ -442,6 +438,16 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
return return
} }
// containsNil reports whether list contains a nil entry.
func containsNil(list []Type) bool {
for _, t := range list {
if t == nil {
return true
}
}
return false
}
// renameTParams renames the type parameters in the given type such that each type // renameTParams renames the type parameters in the given type such that each type
// parameter is given a new identity. renameTParams returns the new type parameters // parameter is given a new identity. renameTParams returns the new type parameters
// and updated type. If the result type is unchanged from the argument type, none // and updated type. If the result type is unchanged from the argument type, none