mirror of https://github.com/golang/go.git
[dev.go2go] go/types: report inferred type when a type argument doesn't match
Fixes #39725. Change-Id: I48248283ae0eb635d489d8661512f32b98700c1a Reviewed-on: https://go-review.googlesource.com/c/go/+/240523 Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
938e96e732
commit
6cf6bf162c
|
|
@ -126,10 +126,11 @@ var tests = [][]string{
|
|||
// TODO(gri) Eliminate the need to enumerate these tests here.
|
||||
// Should just traverse that directory.
|
||||
{"fixedbugs/issue39664.go2"},
|
||||
{"fixedbugs/issue39693.go2"},
|
||||
{"fixedbugs/issue39680.go2"},
|
||||
{"fixedbugs/issue39693.go2"},
|
||||
{"fixedbugs/issue39711.go2"},
|
||||
{"fixedbugs/issue39723.go2"},
|
||||
{"fixedbugs/issue39725.go2"},
|
||||
{"fixedbugs/issue39754.go2"},
|
||||
{"fixedbugs/issue39755.go2"},
|
||||
{"fixedbugs/issue39768.go2"},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2020 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 p
|
||||
|
||||
func f1(type T1, T2)(T1, T2, struct{a T1; b T2})
|
||||
func _() {
|
||||
f1(42, string("foo"), struct /* ERROR does not match inferred type struct\{a int; b string\} */ {a, b int}{})
|
||||
}
|
||||
|
||||
// simplified test case from issue
|
||||
func f2(type T)(_ []T, _ func(T))
|
||||
func _() {
|
||||
f2([]string{}, func /* ERROR does not match inferred type func\(string\) */ (f []byte) {})
|
||||
}
|
||||
|
|
@ -20,13 +20,14 @@ func (check *Checker) infer(pos token.Pos, tparams []*TypeName, params *Tuple, a
|
|||
|
||||
errorf := func(kind string, tpar, targ Type, arg *operand) {
|
||||
// provide a better error message if we can
|
||||
if tpar, _ := tpar.(*TypeParam); tpar != nil {
|
||||
if inferred := u.x.at(tpar.index); inferred != nil {
|
||||
check.errorf(arg.pos(), "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
|
||||
return
|
||||
}
|
||||
targs, _ := u.x.types()
|
||||
smap := makeSubstMap(tparams, targs)
|
||||
inferred := check.subst(arg.pos(), tpar, smap)
|
||||
if inferred != tpar {
|
||||
check.errorf(arg.pos(), "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
|
||||
} else {
|
||||
check.errorf(arg.pos(), "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
|
||||
}
|
||||
check.errorf(arg.pos(), "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
|
||||
}
|
||||
|
||||
// Terminology: generic parameter = function parameter with a type-parameterized type
|
||||
|
|
@ -96,24 +97,22 @@ func (check *Checker) infer(pos token.Pos, tparams []*TypeName, params *Tuple, a
|
|||
|
||||
// Collect type arguments and check if they all have been determined.
|
||||
// TODO(gri) consider moving this outside this function and then we won't need to pass in pos
|
||||
var targs []Type // lazily allocated
|
||||
for i, tpar := range tparams {
|
||||
targ := u.x.at(i)
|
||||
if targ == nil {
|
||||
ppos := check.fset.Position(tpar.pos).String()
|
||||
check.errorf(pos, "cannot infer %s (%s)", tpar.name, ppos)
|
||||
return nil
|
||||
}
|
||||
if targs == nil {
|
||||
targs = make([]Type, len(tparams))
|
||||
}
|
||||
targs[i] = targ
|
||||
targs, failed := u.x.types()
|
||||
if failed >= 0 {
|
||||
tpar := tparams[failed]
|
||||
ppos := check.fset.Position(tpar.pos).String()
|
||||
check.errorf(pos, "cannot infer %s (%s)", tpar.name, ppos)
|
||||
return nil
|
||||
}
|
||||
|
||||
return targs
|
||||
}
|
||||
|
||||
// IsParameterized reports whether typ contains any type parameters.
|
||||
// TODO(gri) This is not strictly correct. We only want the free
|
||||
// type parameters for a given type. (At the moment, the only way
|
||||
// to mix free and bound type parameters is through method type parameters
|
||||
// on parameterized receiver types - need to investigate.)
|
||||
func IsParameterized(typ Type) bool {
|
||||
return isParameterized(typ, make(map[Type]bool))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,23 @@ func (d *typeDesc) at(i int) Type {
|
|||
return nil
|
||||
}
|
||||
|
||||
// types returns the list of inferred types (via unification) for the type parameters
|
||||
// described by d, and an index. If all types were inferred, the returned index is < 0.
|
||||
// Otherwise, it is the index of the first type parameter which couldn't be inferred
|
||||
// and for which list[index] is nil.
|
||||
func (d *typeDesc) types() (list []Type, index int) {
|
||||
list = make([]Type, len(d.tparams))
|
||||
index = -1
|
||||
for i := range d.tparams {
|
||||
t := d.at(i)
|
||||
list[i] = t
|
||||
if index < 0 && t == nil {
|
||||
index = i
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// set sets the type typ inferred (via unification) for the i'th type parameter; typ must not be nil.
|
||||
// The index i must be a valid type parameter index: 0 <= i < len(d.tparams).
|
||||
func (d *typeDesc) set(i int, typ Type) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue