]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: refer to type parameter if so for interface pointer errors
authorRobert Griesemer <gri@golang.org>
Mon, 10 Jan 2022 18:33:16 +0000 (10:33 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 10 Jan 2022 22:49:07 +0000 (22:49 +0000)
Follow-up on comment in CL 376914.

Also:
- add missing check != nil test in assignableTo
- use check.sprintf rather than fmt.Sprintf in missingMethodReason

For #48312.

Change-Id: Ie209b4101a7f2c279e42a59987d0068079c8b69f
Reviewed-on: https://go-review.googlesource.com/c/go/+/377375
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/operand.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2
src/cmd/compile/internal/types2/testdata/fixedbugs/issue48312.go2
src/go/types/call.go
src/go/types/lookup.go
src/go/types/operand.go
src/go/types/testdata/fixedbugs/issue47747.go2
src/go/types/testdata/fixedbugs/issue48312.go2

index 1c3bf48b08c8b8e4c2efd53f2a518bc21d72dc49..ea1c27aa2b4d10a4bbc4e4b7ff038a5c2d3a04d3 100644 (file)
@@ -544,7 +544,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
 
                var why string
                if isInterfacePtr(x.typ) {
-                       why = check.sprintf("type %s is pointer to interface, not interface", x.typ)
+                       why = check.interfacePtrError(x.typ)
                } else {
                        why = check.sprintf("type %s has no field or method %s", x.typ, sel)
                        // Check if capitalization of sel matters and provide better error message in that case.
index aa1ab8ac981e5b9cab70961895244ee45491fc98..5428b667a50400242de0a63c4b36261ddb2c33ad 100644 (file)
@@ -7,7 +7,6 @@
 package types2
 
 import (
-       "fmt"
        "strings"
 )
 
@@ -429,17 +428,17 @@ func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string
        if wrongType != nil {
                if Identical(m.typ, wrongType.typ) {
                        if m.Name() == wrongType.Name() {
-                               r = fmt.Sprintf("(%s has pointer receiver)", mname)
+                               r = check.sprintf("(%s has pointer receiver)", mname)
                        } else {
-                               r = fmt.Sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+                               r = check.sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
                                        mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
                        }
                } else {
                        if check.conf.CompilerErrorMessages {
-                               r = fmt.Sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+                               r = check.sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
                                        mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
                        } else {
-                               r = fmt.Sprintf("(wrong type for %s: have %s, want %s)",
+                               r = check.sprintf("(wrong type for %s: have %s, want %s)",
                                        mname, wrongType.typ, m.typ)
                        }
                }
@@ -450,13 +449,13 @@ func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string
                r = strings.Replace(r, "^^func", "", -1)
        } else if IsInterface(T) {
                if isInterfacePtr(V) {
-                       r = fmt.Sprintf("(type %s is pointer to interface, not interface)", V)
+                       r = "(" + check.interfacePtrError(V) + ")"
                }
        } else if isInterfacePtr(T) {
-               r = fmt.Sprintf("(type %s is pointer to interface, not interface)", T)
+               r = "(" + check.interfacePtrError(T) + ")"
        }
        if r == "" {
-               r = fmt.Sprintf("(missing %s)", mname)
+               r = check.sprintf("(missing %s)", mname)
        }
        return r
 }
@@ -466,6 +465,14 @@ func isInterfacePtr(T Type) bool {
        return p != nil && IsInterface(p.base)
 }
 
+func (check *Checker) interfacePtrError(T Type) string {
+       assert(isInterfacePtr(T))
+       if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
+               return check.sprintf("type %s is pointer to type parameter, not type parameter", T)
+       }
+       return check.sprintf("type %s is pointer to interface, not interface", T)
+}
+
 // assertableTo reports whether a value of type V can be asserted to have type T.
 // It returns (nil, false) as affirmative answer. Otherwise it returns a missing
 // method required by V and whether it is missing or just has the wrong type.
index 69e3a0a8328f52d763db5f401059b3e0cba6d18c..1eb24d136b37f9720c71a2f14497dddbf2f528f5 100644 (file)
@@ -292,7 +292,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
        if Ti, ok := Tu.(*Interface); ok && Tp == nil {
                if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
                        if reason != nil {
-                               if check.conf.CompilerErrorMessages {
+                               if check != nil && check.conf.CompilerErrorMessages {
                                        *reason = check.sprintf("%s does not implement %s %s", x.typ, T,
                                                check.missingMethodReason(x.typ, T, m, wrongType))
                                } else {
index edde497f5aff1023644446e4c693be4193223b09..6f09fc2f57bae1478a6859accdde9a4203e51dba 100644 (file)
@@ -20,7 +20,7 @@ func _[P interface{ m() }](x P) {
         x.m()
         // (&x).m doesn't exist because &x is of type *P
         // and pointers to type parameters don't have methods
-        (&x).m /* ERROR type \*P is pointer to interface, not interface */ ()
+        (&x).m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
 }
 
 
index 6e5911d0aaa650dd6627cc96c082f0b3dc1b16ec..2fdb7cad947113e1a992166a05bc965802c5b98f 100644 (file)
@@ -16,5 +16,5 @@ func _(p P) {
 }
 
 func _[P T](p *P) {
-       p.m /* ERROR type \*P is pointer to interface, not interface */ ()
+       p.m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
 }
index 4a31ec25864be9e2e0588fbd71ef95321422495d..d5b83451c4199003b6db158dddb4240d92314462 100644 (file)
@@ -546,7 +546,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
 
                var why string
                if isInterfacePtr(x.typ) {
-                       why = check.sprintf("type %s is pointer to interface, not interface", x.typ)
+                       why = check.interfacePtrError(x.typ)
                } else {
                        why = check.sprintf("type %s has no field or method %s", x.typ, sel)
                        // Check if capitalization of sel matters and provide better error message in that case.
index 1b820d5403b65afe8872b8e0ac54939c1ccbad74..598f61524771a0b8bbd6a4103c56d5cf1223f22f 100644 (file)
@@ -7,7 +7,6 @@
 package types
 
 import (
-       "fmt"
        "strings"
 )
 
@@ -403,17 +402,17 @@ func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string
        if wrongType != nil {
                if Identical(m.typ, wrongType.typ) {
                        if m.Name() == wrongType.Name() {
-                               r = fmt.Sprintf("(%s has pointer receiver)", mname)
+                               r = check.sprintf("(%s has pointer receiver)", mname)
                        } else {
-                               r = fmt.Sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+                               r = check.sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
                                        mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
                        }
                } else {
                        if compilerErrorMessages {
-                               r = fmt.Sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+                               r = check.sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
                                        mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
                        } else {
-                               r = fmt.Sprintf("(wrong type for %s: have %s, want %s)",
+                               r = check.sprintf("(wrong type for %s: have %s, want %s)",
                                        mname, wrongType.typ, m.typ)
                        }
                }
@@ -424,13 +423,13 @@ func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string
                r = strings.Replace(r, "^^func", "", -1)
        } else if IsInterface(T) {
                if isInterfacePtr(V) {
-                       r = fmt.Sprintf("(type %s is pointer to interface, not interface)", V)
+                       r = "(" + check.interfacePtrError(V) + ")"
                }
        } else if isInterfacePtr(T) {
-               r = fmt.Sprintf("(type %s is pointer to interface, not interface)", T)
+               r = "(" + check.interfacePtrError(T) + ")"
        }
        if r == "" {
-               r = fmt.Sprintf("(missing %s)", mname)
+               r = check.sprintf("(missing %s)", mname)
        }
        return r
 }
@@ -440,6 +439,14 @@ func isInterfacePtr(T Type) bool {
        return p != nil && IsInterface(p.base)
 }
 
+func (check *Checker) interfacePtrError(T Type) string {
+       assert(isInterfacePtr(T))
+       if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
+               return check.sprintf("type %s is pointer to type parameter, not type parameter", T)
+       }
+       return check.sprintf("type %s is pointer to interface, not interface", T)
+}
+
 // assertableTo reports whether a value of type V can be asserted to have type T.
 // It returns (nil, false) as affirmative answer. Otherwise it returns a missing
 // method required by V and whether it is missing or just has the wrong type.
index d669981cf2c7dc2f0f8fd757593aa313bff024a5..d119b5ee7be6c21da2086cbc6815fbda9ba59b0b 100644 (file)
@@ -282,7 +282,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
        if Ti, ok := Tu.(*Interface); ok && Tp == nil {
                if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ {
                        if reason != nil {
-                               if compilerErrorMessages {
+                               if check != nil && compilerErrorMessages {
                                        *reason = check.sprintf("%s does not implement %s %s", x.typ, T,
                                                check.missingMethodReason(x.typ, T, m, wrongType))
                                } else {
index edde497f5aff1023644446e4c693be4193223b09..6f09fc2f57bae1478a6859accdde9a4203e51dba 100644 (file)
@@ -20,7 +20,7 @@ func _[P interface{ m() }](x P) {
         x.m()
         // (&x).m doesn't exist because &x is of type *P
         // and pointers to type parameters don't have methods
-        (&x).m /* ERROR type \*P is pointer to interface, not interface */ ()
+        (&x).m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
 }
 
 
index 6e5911d0aaa650dd6627cc96c082f0b3dc1b16ec..2fdb7cad947113e1a992166a05bc965802c5b98f 100644 (file)
@@ -16,5 +16,5 @@ func _(p P) {
 }
 
 func _[P T](p *P) {
-       p.m /* ERROR type \*P is pointer to interface, not interface */ ()
+       p.m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
 }