]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: fix error message for mismatch between the number of type params and...
authorRaghvender <raghvenders@gmail.com>
Tue, 21 Nov 2023 01:43:13 +0000 (19:43 -0600)
committerGopher Robot <gobot@golang.org>
Fri, 8 Dec 2023 00:50:55 +0000 (00:50 +0000)
Fixes #64276

Change-Id: Ib6651669904e6ea0daf275d85d8bd008b8b21cc6
Reviewed-on: https://go-review.googlesource.com/c/go/+/544018
Reviewed-by: raghvender sundarjee <raghvenders@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

13 files changed:
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/typexpr.go
src/go/types/instantiate.go
src/go/types/typexpr.go
src/internal/types/testdata/check/typeinference.go
src/internal/types/testdata/check/typeinst0.go
src/internal/types/testdata/fixedbugs/issue49541.go
src/internal/types/testdata/fixedbugs/issue50929.go
src/internal/types/testdata/fixedbugs/issue51232.go
src/internal/types/testdata/fixedbugs/issue51233.go
src/internal/types/testdata/fixedbugs/issue51339.go
test/typeparam/issue51232.go
test/typeparam/issue51233.go

index 0c6b202ff9f8e26f8e5d431b17bda3d966181def..e33d4b41c2716b238fc224f3092c4a3520dcb287 100644 (file)
@@ -122,7 +122,8 @@ func (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, expandin
                assert(expanding == nil) // function instances cannot be reached from Named types
 
                tparams := orig.TypeParams()
-               if !check.validateTArgLen(pos, tparams.Len(), len(targs)) {
+               // TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
+               if !check.validateTArgLen(pos, orig.String(), tparams.Len(), len(targs)) {
                        return Typ[Invalid]
                }
                if tparams.Len() == 0 {
@@ -150,19 +151,27 @@ func (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, expandin
        return updateContexts(res)
 }
 
-// validateTArgLen verifies that the length of targs and tparams matches,
-// reporting an error if not. If validation fails and check is nil,
-// validateTArgLen panics.
-func (check *Checker) validateTArgLen(pos syntax.Pos, ntparams, ntargs int) bool {
-       if ntargs != ntparams {
-               // TODO(gri) provide better error message
-               if check != nil {
-                       check.errorf(pos, WrongTypeArgCount, "got %d arguments but %d type parameters", ntargs, ntparams)
-                       return false
-               }
-               panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams))
+// validateTArgLen checks that the number of type arguments (got) matches the
+// number of type parameters (want); if they don't match an error is reported.
+// If validation fails and check is nil, validateTArgLen panics.
+func (check *Checker) validateTArgLen(pos syntax.Pos, name string, want, got int) bool {
+       var qual string
+       switch {
+       case got < want:
+               qual = "not enough"
+       case got > want:
+               qual = "too many"
+       default:
+               return true
        }
-       return true
+
+       msg := check.sprintf("%s type arguments for type %s: have %d, want %d", qual, name, got, want)
+       if check != nil {
+               check.error(atPos(pos), WrongTypeArgCount, msg)
+               return false
+       }
+
+       panic(fmt.Sprintf("%v: %s", pos, msg))
 }
 
 func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type, ctxt *Context) (int, error) {
index 0ee92be6ee5cd23fecb12c8b5b3a5e8c8626cf4e..81adcbd9cfd0105d26eff12c3bbdcf24d2780148 100644 (file)
@@ -463,7 +463,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
                // errors.
                check.recordInstance(x, inst.TypeArgs().list(), inst)
 
-               if check.validateTArgLen(x.Pos(), inst.TypeParams().Len(), inst.TypeArgs().Len()) {
+               if check.validateTArgLen(x.Pos(), inst.obj.name, inst.TypeParams().Len(), inst.TypeArgs().Len()) {
                        if i, err := check.verify(x.Pos(), inst.TypeParams().list(), inst.TypeArgs().list(), check.context()); err != nil {
                                // best position for error reporting
                                pos := x.Pos()
index 34dfd85a260df24e3c015fc6ea524394826dc7f7..bf7ecc531690c6a17e9e392b50ad48bae771d588 100644 (file)
@@ -124,7 +124,8 @@ func (check *Checker) instance(pos token.Pos, orig Type, targs []Type, expanding
                assert(expanding == nil) // function instances cannot be reached from Named types
 
                tparams := orig.TypeParams()
-               if !check.validateTArgLen(pos, tparams.Len(), len(targs)) {
+               // TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
+               if !check.validateTArgLen(pos, orig.String(), tparams.Len(), len(targs)) {
                        return Typ[Invalid]
                }
                if tparams.Len() == 0 {
@@ -152,19 +153,27 @@ func (check *Checker) instance(pos token.Pos, orig Type, targs []Type, expanding
        return updateContexts(res)
 }
 
-// validateTArgLen verifies that the length of targs and tparams matches,
-// reporting an error if not. If validation fails and check is nil,
-// validateTArgLen panics.
-func (check *Checker) validateTArgLen(pos token.Pos, ntparams, ntargs int) bool {
-       if ntargs != ntparams {
-               // TODO(gri) provide better error message
-               if check != nil {
-                       check.errorf(atPos(pos), WrongTypeArgCount, "got %d arguments but %d type parameters", ntargs, ntparams)
-                       return false
-               }
-               panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams))
+// validateTArgLen checks that the number of type arguments (got) matches the
+// number of type parameters (want); if they don't match an error is reported.
+// If validation fails and check is nil, validateTArgLen panics.
+func (check *Checker) validateTArgLen(pos token.Pos, name string, want, got int) bool {
+       var qual string
+       switch {
+       case got < want:
+               qual = "not enough"
+       case got > want:
+               qual = "too many"
+       default:
+               return true
        }
-       return true
+
+       msg := check.sprintf("%s type arguments for type %s: have %d, want %d", qual, name, got, want)
+       if check != nil {
+               check.error(atPos(pos), WrongTypeArgCount, msg)
+               return false
+       }
+
+       panic(fmt.Sprintf("%v: %s", pos, msg))
 }
 
 func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type, ctxt *Context) (int, error) {
index 2835958d9842c8bffe10501f1bc512d0ae2ce180..c887b5115a2ab13183698a40d5b1e533f219df59 100644 (file)
@@ -454,7 +454,7 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *TypeName)
                // errors.
                check.recordInstance(ix.Orig, inst.TypeArgs().list(), inst)
 
-               if check.validateTArgLen(ix.Pos(), inst.TypeParams().Len(), inst.TypeArgs().Len()) {
+               if check.validateTArgLen(ix.Pos(), inst.obj.name, inst.TypeParams().Len(), inst.TypeArgs().Len()) {
                        if i, err := check.verify(ix.Pos(), inst.TypeParams().list(), inst.TypeArgs().list(), check.context()); err != nil {
                                // best position for error reporting
                                pos := ix.Pos()
index 0478d9390f92e994387676b6ae1032c4161d1324..8dac938ef962681f09967421303ee30b9eae5db8 100644 (file)
@@ -8,8 +8,9 @@ package typeInference
 
 // basic inference
 type Tb[P ~*Q, Q any] int
+
 func _() {
-       var x Tb /* ERROR "got 1 arguments" */ [*int]
+       var x Tb /* ERROR "not enough type arguments for type Tb: have 1, want 2" */ [*int]
        var y Tb[*int, int]
        x = y /* ERRORx `cannot use y .* in assignment` */
        _ = x
@@ -17,8 +18,9 @@ func _() {
 
 // recursive inference
 type Tr[A any, B *C, C *D, D *A] int
+
 func _() {
-       var x Tr /* ERROR "got 1 arguments" */ [string]
+       var x Tr /* ERROR "not enough type arguments for type Tr: have 1, want 4" */ [string]
        var y Tr[string, ***string, **string, *string]
        var z Tr[int, ***int, **int, *int]
        x = y /* ERRORx `cannot use y .* in assignment` */
@@ -28,22 +30,30 @@ func _() {
 
 // other patterns of inference
 type To0[A any, B []A] int
-type To1[A any, B struct{a A}] int
+type To1[A any, B struct{ a A }] int
 type To2[A any, B [][]A] int
 type To3[A any, B [3]*A] int
-type To4[A any, B any, C struct{a A; b B}] int
+type To4[A any, B any, C struct {
+       a A
+       b B
+}] int
+
 func _() {
-       var _ To0 /* ERROR "got 1 arguments" */ [int]
-       var _ To1 /* ERROR "got 1 arguments" */ [int]
-       var _ To2 /* ERROR "got 1 arguments" */ [int]
-       var _ To3 /* ERROR "got 1 arguments" */ [int]
-       var _ To4 /* ERROR "got 2 arguments" */ [int, string]
+       var _ To0 /* ERROR "not enough type arguments for type To0: have 1, want 2" */ [int]
+       var _ To1 /* ERROR "not enough type arguments for type To1: have 1, want 2" */ [int]
+       var _ To2 /* ERROR "not enough type arguments for type To2: have 1, want 2" */ [int]
+       var _ To3 /* ERROR "not enough type arguments for type To3: have 1, want 2" */ [int]
+       var _ To4 /* ERROR "not enough type arguments for type To4: have 2, want 3" */ [int, string]
 }
 
 // failed inference
 type Tf0[A, B any] int
-type Tf1[A any, B ~struct{a A; c C}, C any] int
+type Tf1[A any, B ~struct {
+       a A
+       c C
+}, C any] int
+
 func _() {
-       var _ Tf0 /* ERROR "got 1 arguments but 2 type parameters" */ [int]
-       var _ Tf1 /* ERROR "got 1 arguments but 3 type parameters" */ [int]
+       var _ Tf0 /* ERROR "not enough type arguments for type Tf0: have 1, want 2" */ [int]
+       var _ Tf1 /* ERROR "not enough type arguments for type Tf1: have 1, want 3" */ [int]
 }
index bbcdaec04a8bd4ab696f2ae29907af8366af0351..155f1ef4400f44302d76e6242815d7b49ab210d3 100644 (file)
@@ -42,7 +42,7 @@ type _ myInt /* ERROR "not a generic type" */ [] // ERROR "expected type argumen
 // TODO(gri) better error messages
 type _ T1[] // ERROR "expected type argument list"
 type _ T1[x /* ERROR "not a type" */ ]
-type _ T1 /* ERROR "got 2 arguments but 1 type parameters" */ [int, float32]
+type _ T1 /* ERROR "too many type arguments for type T1: have 2, want 1" */ [int, float32]
 
 var _ T2[int] = T2[int]{}
 
index da3731195be037b5722509c9ce13cf9dc0a19efb..665ed1da7c7a1f17f5c764fcc082843476c859cf 100644 (file)
@@ -13,7 +13,7 @@ func (S[A, B]) m() {}
 // TODO(gri): with type-type inference enabled we should only report one error
 // below. See issue #50588.
 
-func _[A any](s S /* ERROR "got 1 arguments but 2 type parameters" */ [A]) {
+func _[A any](s S /* ERROR "not enough type arguments for type S: have 1, want 2" */ [A]) {
        // we should see no follow-on errors below
        s.f = 1
        s.m()
@@ -22,7 +22,7 @@ func _[A any](s S /* ERROR "got 1 arguments but 2 type parameters" */ [A]) {
 // another test case from the issue
 
 func _() {
-       X /* ERROR "cannot infer Q" */ (Interface[*F /* ERROR "got 1 arguments but 2 type parameters" */ [string]](Impl{}))
+       X /* ERROR "cannot infer Q" */ (Interface[*F /* ERROR "not enough type arguments for type F: have 1, want 2" */ [string]](Impl{}))
 }
 
 func X[Q Qer](fs Interface[Q]) {
index 64c7cd664f3c845503607a4ab663a7a19cb4671a..a665e229be0627d1e14bd7bc8fd4ff46a7bcd792 100644 (file)
@@ -16,7 +16,7 @@ func G[A, B any](F[A, B]) {
 
 func _() {
        // TODO(gri) only report one error below (issue #50932)
-       var x F /* ERROR "got 1 arguments but 2 type parameters" */ [int]
+       var x F /* ERROR "not enough type arguments for type F: have 1, want 2" */ [int]
        G(x /* ERROR "does not match" */)
 }
 
@@ -46,9 +46,9 @@ func NSG[G any](c RSC[G]) {
        fmt.Println(c)
 }
 
-func MMD[Rc RC /* ERROR "got 1 arguments" */ [RG], RG any, G any]() M /* ERROR "got 2 arguments" */ [Rc, RG] {
+func MMD[Rc RC /* ERROR "not enough type arguments for type RC: have 1, want 2" */ [RG], RG any, G any]() M /* ERROR "not enough type arguments for type" */ [Rc, RG] {
 
-       var nFn NFn /* ERROR "got 2 arguments" */ [Rc, RG]
+       var nFn NFn /* ERROR "not enough type arguments for type NFn: have 2, want 3" */ [Rc, RG]
 
        var empty Rc
        switch any(empty).(type) {
@@ -58,11 +58,11 @@ func MMD[Rc RC /* ERROR "got 1 arguments" */ [RG], RG any, G any]() M /* ERROR "
                nFn = NSG /* ERROR "cannot use NSG[G]" */ [G]
        }
 
-       return M /* ERROR "got 2 arguments" */ [Rc, RG]{
+       return M /* ERROR "not enough type arguments for type M: have 2, want 3" */ [Rc, RG]{
                Fn: func(rc Rc) {
-                       NC(nFn /* ERROR "does not match" */ )
+                       NC(nFn /* ERROR "does not match" */)
                },
        }
 
-       return M /* ERROR "got 2 arguments" */ [Rc, RG]{}
+       return M /* ERROR "not enough type arguments for type M: have 2, want 3" */ [Rc, RG]{}
 }
index 27693a3e4d03ad64e7e06426415b18ceb6c4b5a0..c5832d2976914c7c9edbab6c7e8663f93f9ea699 100644 (file)
@@ -11,20 +11,20 @@ type RC[RG any] interface {
 type Fn[RCT RC[RG], RG any] func(RCT)
 
 type F[RCT RC[RG], RG any] interface {
-       Fn() Fn /* ERROR "got 1 arguments" */ [RCT]
+       Fn() Fn /* ERROR "not enough type arguments for type Fn: have 1, want 2" */ [RCT]
 }
 
 type concreteF[RCT RC[RG], RG any] struct {
-       makeFn func() Fn /* ERROR "got 1 arguments" */ [RCT]
+       makeFn func() Fn /* ERROR "not enough type arguments for type Fn: have 1, want 2" */ [RCT]
 }
 
-func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR "got 1 arguments" */ [RCT] {
+func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR "not enough type arguments for type Fn: have 1, want 2" */ [RCT] {
        return c.makeFn()
 }
 
-func NewConcrete[RCT RC[RG], RG any](Rc RCT) F /* ERROR "got 1 arguments" */ [RCT] {
+func NewConcrete[RCT RC[RG], RG any](Rc RCT) F /* ERROR "not enough type arguments for type F: have 1, want 2" */ [RCT] {
        // TODO(rfindley): eliminate the duplicate error below.
-       return & /* ERRORx `cannot use .* as F\[RCT\]` */ concreteF /* ERROR "got 1 arguments" */ [RCT]{
+       return & /* ERRORx `cannot use .* as F\[RCT\]` */ concreteF /* ERROR "not enough type arguments for type concreteF: have 1, want 2" */ [RCT]{
                makeFn: nil,
        }
 }
index e2f97fc45650a6965fa0ceca2a8bfeedb17fad1f..d96d3d1aa07fb2d10451b11cd305c1ad13201a85 100644 (file)
@@ -12,16 +12,16 @@ type RC[RG any] interface {
 
 type Fn[RCT RC[RG], RG any] func(RCT)
 
-type FFn[RCT RC[RG], RG any] func() Fn /* ERROR "got 1 arguments" */ [RCT]
+type FFn[RCT RC[RG], RG any] func() Fn /* ERROR "not enough type arguments for type Fn: have 1, want 2" */ [RCT]
 
 type F[RCT RC[RG], RG any] interface {
-       Fn() Fn /* ERROR "got 1 arguments" */ [RCT]
+       Fn() Fn /* ERROR "not enough type arguments for type Fn: have 1, want 2" */ [RCT]
 }
 
 type concreteF[RCT RC[RG], RG any] struct {
-       makeFn FFn /* ERROR "got 1 arguments" */ [RCT]
+       makeFn FFn /* ERROR "not enough type arguments for type FFn: have 1, want 2" */ [RCT]
 }
 
-func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR "got 1 arguments" */ [RCT] {
+func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR "not enough type arguments for type Fn: have 1, want 2" */ [RCT] {
        return c.makeFn()
 }
index 65c213462ba70cad1f9bb3c8abed8247a2486770..fd10daa2c24f10d903e71ef1cb293050d721b2f4 100644 (file)
@@ -9,10 +9,12 @@ package p
 
 type T[P any, B *P] struct{}
 
-func (T /* ERROR "cannot use generic type" */ ) m0() {}
+func (T /* ERROR "cannot use generic type" */) m0() {}
 
 // TODO(rfindley): eliminate the duplicate errors here.
-func (/* ERROR "got 1 type parameter, but receiver base type declares 2" */ T /* ERROR "got 1 arguments but 2 type parameters" */ [_]) m1() {}
+func ( /* ERROR "got 1 type parameter, but receiver base type declares 2" */ T /* ERROR "not enough type arguments for type" */ [_]) m1() {
+}
 func (T[_, _]) m2() {}
+
 // TODO(gri) this error is unfortunate (issue #51343)
-func (T /* ERROR "got 3 arguments but 2 type parameters" */ [_, _, _]) m3() {}
+func (T /* ERROR "too many type arguments for type" */ [_, _, _]) m3() {}
index 0d25e1863d70077d0f930e63994cad7a8fb60082..f4728f6e7cd310776a5adee13dda99a40e654a15 100644 (file)
@@ -13,19 +13,19 @@ type RC[RG any] interface {
 type Fn[RCT RC[RG], RG any] func(RCT)
 
 type F[RCT RC[RG], RG any] interface {
-       Fn() Fn[RCT] // ERROR "got 1 arguments"
+       Fn() Fn[RCT] // ERROR "not enough type arguments for type Fn: have 1, want 2"
 }
 
 type concreteF[RCT RC[RG], RG any] struct {
-       makeFn func() Fn[RCT] // ERROR "got 1 arguments"
+       makeFn func() Fn[RCT] // ERROR "not enough type arguments for type Fn: have 1, want 2"
 }
 
-func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { // ERROR "got 1 arguments"
+func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { // ERROR "not enough type arguments for type Fn: have 1, want 2"
        return c.makeFn()
 }
 
-func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] { // ERROR "got 1 arguments"
-       return &concreteF[RCT]{ // ERROR "cannot use" "got 1 arguments"
+func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] { // ERROR "not enough type arguments for type F: have 1, want 2"
+       return &concreteF[RCT]{ // ERROR "cannot use" "not enough type arguments for type concreteF: have 1, want 2"
                makeFn: nil,
        }
 }
index 96a25ddb9c3952e54d227e94e8bb87a1eb1a2710..5f2a045d84735704d8c63d5bab88337424ded6f9 100644 (file)
@@ -13,16 +13,16 @@ type RC[RG any] interface {
 
 type Fn[RCT RC[RG], RG any] func(RCT)
 
-type FFn[RCT RC[RG], RG any] func() Fn[RCT] // ERROR "got 1 arguments"
+type FFn[RCT RC[RG], RG any] func() Fn[RCT] // ERROR "not enough type arguments for type Fn: have 1, want 2"
 
 type F[RCT RC[RG], RG any] interface {
-       Fn() Fn[RCT] // ERROR "got 1 arguments"
+       Fn() Fn[RCT] // ERROR "not enough type arguments for type Fn: have 1, want 2"
 }
 
 type concreteF[RCT RC[RG], RG any] struct {
-       makeFn FFn[RCT] // ERROR "got 1 arguments"
+       makeFn FFn[RCT] // ERROR "not enough type arguments for type FFn: have 1, want 2"
 }
 
-func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { // ERROR "got 1 arguments"
+func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { // ERROR "not enough type arguments for type Fn: have 1, want 2"
        return c.makeFn()
 }