]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: add predicate to missingMethod signature
authorRobert Griesemer <gri@golang.org>
Tue, 28 Feb 2023 23:04:35 +0000 (15:04 -0800)
committerGopher Robot <gobot@golang.org>
Wed, 1 Mar 2023 21:23:50 +0000 (21:23 +0000)
This allows us to use missingMethod with different type comparers,
such as the global Identical predicate, or a unifier.

Preparation for the next CL.

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

src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/lookup.go
src/go/types/instantiate.go
src/go/types/lookup.go

index 9f5eb268ac7496812b5b13e6e3d125537bc7f22d..7091ef7e49264f7f37949e6a2b94dffd7f245eb5 100644 (file)
@@ -241,7 +241,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
        }
 
        // V must implement T's methods, if any.
-       if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
+       if m, wrong := check.missingMethod(V, Ti, true, Identical); m != nil /* !Implements(V, Ti) */ {
                if cause != nil {
                        *cause = check.sprintf("%s does not %s %s %s", V, verb, T, check.missingMethodCause(V, T, m, wrong))
                }
index 0c3b96ff2d282ebc8ff66724e74830b0bd298b98..7d3417924997793487fb0cad6b44eae2fbb5c4b3 100644 (file)
@@ -305,20 +305,22 @@ func (l *instanceLookup) add(inst *Named) {
 // present in V have matching types (e.g., for a type assertion x.(T) where
 // x is of interface type V).
 func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) {
-       m, alt := (*Checker)(nil).missingMethod(V, T, static)
+       m, alt := (*Checker)(nil).missingMethod(V, T, static, Identical)
        // Only report a wrong type if the alternative method has the same name as m.
        return m, alt != nil && alt.name == m.name // alt != nil implies m != nil
 }
 
-// missingMethod is like MissingMethod but accepts a *Checker as receiver.
+// missingMethod is like MissingMethod but accepts a *Checker as receiver
+// and comparator equivalent for type comparison.
 // The receiver may be nil if missingMethod is invoked through an exported
 // API call (such as MissingMethod), i.e., when all methods have been type-
 // checked.
+// The comparator is used to compare signatures.
 //
 // If a method is missing on T but is found on *T, or if a method is found
 // on T when looked up with case-folding, this alternative method is returned
 // as the second result.
-func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
+func (check *Checker) missingMethod(V Type, T *Interface, static bool, equivalent func(x, y Type) bool) (method, alt *Func) {
        if T.NumMethods() == 0 {
                return
        }
@@ -336,7 +338,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                                return m, nil
                        }
 
-                       if !Identical(f.typ, m.typ) {
+                       if !equivalent(f.typ, m.typ) {
                                return m, f
                        }
                }
@@ -370,7 +372,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                        check.objDecl(f, nil)
                }
 
-               if !found || !Identical(f.typ, m.typ) {
+               if !found || !equivalent(f.typ, m.typ) {
                        return m, f
                }
        }
@@ -467,7 +469,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun
                return
        }
        // TODO(gri) fix this for generalized interfaces
-       return check.missingMethod(T, V, false)
+       return check.missingMethod(T, V, false, Identical)
 }
 
 // newAssertableTo reports whether a value of type V can be asserted to have type T.
index 11afb7a853e41b8679da7c70b3feb1e33d7a2dd3..2a9182d5afbdeee4c0a038b1b58a538d37fd508b 100644 (file)
@@ -243,7 +243,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
        }
 
        // V must implement T's methods, if any.
-       if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
+       if m, wrong := check.missingMethod(V, Ti, true, Identical); m != nil /* !Implements(V, Ti) */ {
                if cause != nil {
                        *cause = check.sprintf("%s does not %s %s %s", V, verb, T, check.missingMethodCause(V, T, m, wrong))
                }
index 331c308656e24b238497850851c508c698eccdbb..f9e297044e9fb1366633c79082514ba737ea3c60 100644 (file)
@@ -307,20 +307,22 @@ func (l *instanceLookup) add(inst *Named) {
 // present in V have matching types (e.g., for a type assertion x.(T) where
 // x is of interface type V).
 func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) {
-       m, alt := (*Checker)(nil).missingMethod(V, T, static)
+       m, alt := (*Checker)(nil).missingMethod(V, T, static, Identical)
        // Only report a wrong type if the alternative method has the same name as m.
        return m, alt != nil && alt.name == m.name // alt != nil implies m != nil
 }
 
-// missingMethod is like MissingMethod but accepts a *Checker as receiver.
+// missingMethod is like MissingMethod but accepts a *Checker as receiver
+// and comparator equivalent for type comparison.
 // The receiver may be nil if missingMethod is invoked through an exported
 // API call (such as MissingMethod), i.e., when all methods have been type-
 // checked.
+// The comparator is used to compare signatures.
 //
 // If a method is missing on T but is found on *T, or if a method is found
 // on T when looked up with case-folding, this alternative method is returned
 // as the second result.
-func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
+func (check *Checker) missingMethod(V Type, T *Interface, static bool, equivalent func(x, y Type) bool) (method, alt *Func) {
        if T.NumMethods() == 0 {
                return
        }
@@ -338,7 +340,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                                return m, nil
                        }
 
-                       if !Identical(f.typ, m.typ) {
+                       if !equivalent(f.typ, m.typ) {
                                return m, f
                        }
                }
@@ -372,7 +374,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                        check.objDecl(f, nil)
                }
 
-               if !found || !Identical(f.typ, m.typ) {
+               if !found || !equivalent(f.typ, m.typ) {
                        return m, f
                }
        }
@@ -469,7 +471,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun
                return
        }
        // TODO(gri) fix this for generalized interfaces
-       return check.missingMethod(T, V, false)
+       return check.missingMethod(T, V, false, Identical)
 }
 
 // newAssertableTo reports whether a value of type V can be asserted to have type T.