]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: better error when method is missing due to ambiguity
authorRobert Griesemer <gri@golang.org>
Mon, 6 Mar 2023 21:05:29 +0000 (13:05 -0800)
committerGopher Robot <gobot@golang.org>
Mon, 6 Mar 2023 21:22:00 +0000 (21:22 +0000)
If a type doesn't implement an interface due to an ambiguous method,
say so in the error message instead of just reporting a missing method.

Fixes #57352.

Change-Id: I5608f893c485de578b7f86362ca6f66033653695
Reviewed-on: https://go-review.googlesource.com/c/go/+/473658
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>

src/cmd/compile/internal/types2/lookup.go
src/go/types/lookup.go
src/internal/types/testdata/check/decls4.go
src/internal/types/testdata/fixedbugs/issue57352.go [new file with mode: 0644]

index 855bf2a24c1980465f54214e438cdce911679819..d2694fc974b0c5c548c34d70eb2672343d4aacf6 100644 (file)
@@ -343,6 +343,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
                notFound
                wrongName
                wrongSig
+               ambigSel
                ptrRecv
                field
        )
@@ -371,21 +372,23 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
                }
        } else {
                for _, m = range methods {
-                       obj, _, indirect := lookupFieldOrMethodImpl(V, false, m.pkg, m.name, false)
+                       obj, index, indirect := lookupFieldOrMethodImpl(V, false, m.pkg, m.name, false)
 
-                       // check if m is on *V, or on V with case-folding
+                       // check if m is ambiguous, on *V, or on V with case-folding
                        if obj == nil {
-                               if indirect {
+                               switch {
+                               case index != nil:
+                                       state = ambigSel
+                               case indirect:
                                        state = ptrRecv
-                                       break
-                               }
-                               obj, _, _ = lookupFieldOrMethodImpl(V, false, m.pkg, m.name, true /* fold case */)
-                               f, _ = obj.(*Func)
-                               if f != nil {
-                                       state = wrongName
-                                       break
+                               default:
+                                       state = notFound
+                                       obj, _, _ = lookupFieldOrMethodImpl(V, false, m.pkg, m.name, true /* fold case */)
+                                       f, _ = obj.(*Func)
+                                       if f != nil {
+                                               state = wrongName
+                                       }
                                }
-                               state = notFound
                                break
                        }
 
@@ -436,6 +439,8 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
                        }
                        *cause = check.sprintf("(wrong type for method %s)\n\t\thave %s\n\t\twant %s",
                                m.Name(), fs, ms)
+               case ambigSel:
+                       *cause = check.sprintf("(ambiguous selector %s.%s)", V, m.Name())
                case ptrRecv:
                        *cause = check.sprintf("(method %s has pointer receiver)", m.Name())
                case field:
index a2f7e7ea50e274c7fafded5ff65d66d6bb7792b3..9e6367f9c9f28138291592f9d922adc1bac91dae 100644 (file)
@@ -345,6 +345,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
                notFound
                wrongName
                wrongSig
+               ambigSel
                ptrRecv
                field
        )
@@ -373,21 +374,23 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
                }
        } else {
                for _, m = range methods {
-                       obj, _, indirect := lookupFieldOrMethodImpl(V, false, m.pkg, m.name, false)
+                       obj, index, indirect := lookupFieldOrMethodImpl(V, false, m.pkg, m.name, false)
 
-                       // check if m is on *V, or on V with case-folding
+                       // check if m is ambiguous, on *V, or on V with case-folding
                        if obj == nil {
-                               if indirect {
+                               switch {
+                               case index != nil:
+                                       state = ambigSel
+                               case indirect:
                                        state = ptrRecv
-                                       break
-                               }
-                               obj, _, _ = lookupFieldOrMethodImpl(V, false, m.pkg, m.name, true /* fold case */)
-                               f, _ = obj.(*Func)
-                               if f != nil {
-                                       state = wrongName
-                                       break
+                               default:
+                                       state = notFound
+                                       obj, _, _ = lookupFieldOrMethodImpl(V, false, m.pkg, m.name, true /* fold case */)
+                                       f, _ = obj.(*Func)
+                                       if f != nil {
+                                               state = wrongName
+                                       }
                                }
-                               state = notFound
                                break
                        }
 
@@ -438,6 +441,8 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
                        }
                        *cause = check.sprintf("(wrong type for method %s)\n\t\thave %s\n\t\twant %s",
                                m.Name(), fs, ms)
+               case ambigSel:
+                       *cause = check.sprintf("(ambiguous selector %s.%s)", V, m.Name())
                case ptrRecv:
                        *cause = check.sprintf("(method %s has pointer receiver)", m.Name())
                case field:
index 6ad20b6502c8273c42dc6ad67fba756fa881a4d5..c47a68d525ec858302315955ee0bc6f6a436231a 100644 (file)
@@ -195,5 +195,5 @@ var (
 )
 
 var (
-       _ interface{ xm() } = eD /* ERROR "missing method xm" */ {}
+       _ interface{ xm() } = eD /* ERROR "ambiguous selector eD.xm" */ {}
 )
\ No newline at end of file
diff --git a/src/internal/types/testdata/fixedbugs/issue57352.go b/src/internal/types/testdata/fixedbugs/issue57352.go
new file mode 100644 (file)
index 0000000..2b31700
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2023 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
+
+type A interface {
+       a()
+}
+
+type AB interface {
+       A
+       b()
+}
+
+type AAB struct {
+       A
+       AB
+}
+
+var _ AB = AAB /* ERROR "ambiguous selector AAB.a" */ {}