]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: use same method lookup code in both type checkers
authorRobert Griesemer <gri@golang.org>
Wed, 2 Feb 2022 21:18:56 +0000 (13:18 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 4 Feb 2022 23:42:35 +0000 (23:42 +0000)
types2 has some code to handle case-folding when doing method lookups
which was missing in go/types. This change is a first step to match
the implementations. Specifically:

In types2:
- remove the lookupMethodFold names in favor of just lookupMethod,
  but with the foldCase flag (e.g., instead if lookupMethodFold,
  we just use lookupMethod)
- rename checkFold to foldCase everywhere
- add foldCase parameter where it was missing
- moved foldCase paremeter to the end in lookupFieldOrMethod
- no functionality changes

In go/types:
- match function signatures with types2 use
- always provide false as argument for foldCase for now
- no functionality changes

Preparation for fixing some of the outstanding error reporting issues.

Change-Id: If129a5feb89ddf96a3596e8d73b23afa591875a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/382461
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/methodlist.go
src/cmd/compile/internal/types2/named.go
src/cmd/compile/internal/types2/typeset.go
src/go/types/lookup.go
src/go/types/methodlist.go
src/go/types/named.go
src/go/types/typeset.go

index a71dd409e13ee20d915e68c7ba502c3482a52752..407b8384df98ec466f6891d8e21e6d0b9d7c4cc7 100644 (file)
@@ -55,7 +55,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
        // not have found it for T (see also issue 8590).
        if t, _ := T.(*Named); t != nil {
                if p, _ := t.Underlying().(*Pointer); p != nil {
-                       obj, index, indirect = lookupFieldOrMethod(p, false, false, pkg, name)
+                       obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name, false)
                        if _, ok := obj.(*Func); ok {
                                return nil, nil, false
                        }
@@ -63,7 +63,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
                }
        }
 
-       obj, index, indirect = lookupFieldOrMethod(T, addressable, false, pkg, name)
+       obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false)
 
        // If we didn't find anything and if we have a type parameter with a structural constraint,
        // see if there is a matching field (but not a method, those need to be declared explicitly
@@ -71,7 +71,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
        // are ok here because only fields are accepted as results.
        if obj == nil && isTypeParam(T) {
                if t := structuralType(T); t != nil {
-                       obj, index, indirect = lookupFieldOrMethod(t, addressable, false, pkg, name)
+                       obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
                        if _, ok := obj.(*Var); !ok {
                                obj, index, indirect = nil, nil, false // accept fields (variables) only
                        }
@@ -86,11 +86,11 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 //           indirectly via different packages.)
 
 // lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
-// If checkFold is true, the lookup for methods will include looking for any method
+// If foldCase is true, the lookup for methods will include looking for any method
 // which case-folds to the same as 'name' (used for giving helpful error messages).
 //
 // The resulting object may not be fully type-checked.
-func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, foldCase bool) (obj Object, index []int, indirect bool) {
        // WARNING: The code in this function is extremely subtle - do not modify casually!
 
        if name == "_" {
@@ -144,7 +144,7 @@ func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name
 
                                // look for a matching attached method
                                named.resolve(nil)
-                               if i, m := named.lookupMethodFold(pkg, name, checkFold); m != nil {
+                               if i, m := named.lookupMethod(pkg, name, foldCase); m != nil {
                                        // potential match
                                        // caution: method may not have a proper signature yet
                                        index = concat(e.index, i)
@@ -191,7 +191,7 @@ func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name
 
                        case *Interface:
                                // look for a matching method (interface may be a type parameter)
-                               if i, m := lookupMethodFold(t.typeSet().methods, pkg, name, checkFold); m != nil {
+                               if i, m := t.typeSet().LookupMethod(pkg, name, foldCase); m != nil {
                                        assert(m.typ != nil)
                                        index = concat(e.index, i)
                                        if obj != nil || e.multiples {
@@ -308,7 +308,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
        if ityp, _ := under(V).(*Interface); ityp != nil {
                // TODO(gri) the methods are sorted - could do this more efficiently
                for _, m := range T.typeSet().methods {
-                       _, f := ityp.typeSet().LookupMethod(m.pkg, m.name)
+                       _, f := ityp.typeSet().LookupMethod(m.pkg, m.name, false)
 
                        if f == nil {
                                if !static {
@@ -339,17 +339,17 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
        // A concrete type implements T if it implements all methods of T.
        for _, m := range T.typeSet().methods {
                // TODO(gri) should this be calling LookupFieldOrMethod instead (and why not)?
-               obj, _, _ := lookupFieldOrMethod(V, false, false, m.pkg, m.name)
+               obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name, false)
 
                // Check if *V implements this method of T.
                if obj == nil {
                        ptr := NewPointer(V)
-                       obj, _, _ = lookupFieldOrMethod(ptr, false, false, m.pkg, m.name)
+                       obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name, false)
                        if obj == nil {
                                // If we didn't find the exact method (even with pointer
                                // receiver), look to see if there is a method that
                                // matches m.name with case-folding.
-                               obj, _, _ = lookupFieldOrMethod(V, false, true, m.pkg, m.name)
+                               obj, _, _ = lookupFieldOrMethod(V, false, m.pkg, m.name, true)
                        }
                        if obj != nil {
                                // methods may not have a fully set up signature yet
@@ -513,28 +513,11 @@ func fieldIndex(fields []*Var, pkg *Package, name string) int {
 }
 
 // lookupMethod returns the index of and method with matching package and name, or (-1, nil).
-func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
+// If foldCase is true, method names are considered equal if they are equal with case folding.
+func lookupMethod(methods []*Func, pkg *Package, name string, foldCase bool) (int, *Func) {
        if name != "_" {
                for i, m := range methods {
-                       if m.sameId(pkg, name) {
-                               return i, m
-                       }
-               }
-       }
-       return -1, nil
-}
-
-// lookupMethodFold is like lookupMethod, but if checkFold is true, it matches a method
-// name if the names are equal with case folding.
-func lookupMethodFold(methods []*Func, pkg *Package, name string, checkFold bool) (int, *Func) {
-       if name != "_" {
-               for i, m := range methods {
-                       if m.name != name && !(checkFold && strings.EqualFold(m.name, name)) {
-                               continue
-                       }
-                       // Use m.name, since we've already checked that m.name and
-                       // name are equal with folding.
-                       if m.sameId(pkg, m.name) {
+                       if (m.name == name || foldCase && strings.EqualFold(m.name, name)) && m.sameId(pkg, m.name) {
                                return i, m
                        }
                }
index ba10159ea265b72de9915c61e5cadb459b8ada91..cd6c06c5fb5d7199a7e3f48763fbbd84d7ffc629 100644 (file)
@@ -41,20 +41,20 @@ func (l *methodList) isLazy() bool {
 // panics if the receiver is lazy.
 func (l *methodList) Add(m *Func) {
        assert(!l.isLazy())
-       if i, _ := lookupMethod(l.methods, m.pkg, m.name); i < 0 {
+       if i, _ := lookupMethod(l.methods, m.pkg, m.name, false); i < 0 {
                l.methods = append(l.methods, m)
        }
 }
 
-// LookupFold looks up the method identified by pkg and name in the receiver.
-// LookupFold panics if the receiver is lazy. If checkFold is true, it matches
-// a method name if the names are equal with case folding.
-func (l *methodList) LookupFold(pkg *Package, name string, checkFold bool) (int, *Func) {
+// Lookup looks up the method identified by pkg and name in the receiver.
+// Lookup panics if the receiver is lazy. If foldCase is true, method names
+// are considered equal if they are equal with case folding.
+func (l *methodList) Lookup(pkg *Package, name string, foldCase bool) (int, *Func) {
        assert(!l.isLazy())
        if l == nil {
                return -1, nil
        }
-       return lookupMethodFold(l.methods, pkg, name, checkFold)
+       return lookupMethod(l.methods, pkg, name, foldCase)
 }
 
 // Len returns the length of the method list.
index 5248893a4a4149b5bf593e2d1aec16a8425fed9e..bb522e8fe37f8372d591ebfc42d758fd64f17274 100644 (file)
@@ -297,12 +297,12 @@ func (n *Named) setUnderlying(typ Type) {
        }
 }
 
-func (n *Named) lookupMethodFold(pkg *Package, name string, checkFold bool) (int, *Func) {
+func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
        n.resolve(nil)
        // If n is an instance, we may not have yet instantiated all of its methods.
        // Look up the method index in orig, and only instantiate method at the
        // matching index (if any).
-       i, _ := n.orig.methods.LookupFold(pkg, name, checkFold)
+       i, _ := n.orig.methods.Lookup(pkg, name, foldCase)
        if i < 0 {
                return -1, nil
        }
index 3884276adc5bd32ae933a7de74a5895d7f58e549..fff348bcf4361bcc8a32a6c4ab095514c2a45a82 100644 (file)
@@ -58,9 +58,8 @@ func (s *_TypeSet) NumMethods() int { return len(s.methods) }
 func (s *_TypeSet) Method(i int) *Func { return s.methods[i] }
 
 // LookupMethod returns the index of and method with matching package and name, or (-1, nil).
-func (s *_TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) {
-       // TODO(gri) s.methods is sorted - consider binary search
-       return lookupMethod(s.methods, pkg, name)
+func (s *_TypeSet) LookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
+       return lookupMethod(s.methods, pkg, name, foldCase)
 }
 
 func (s *_TypeSet) String() string {
index bee76ccb55f36789e4b9c6e7e14db1d1413ac7b4..59cec23035f56a4e913bb9df78e380875085c3a1 100644 (file)
@@ -55,7 +55,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
        // not have found it for T (see also issue 8590).
        if t, _ := T.(*Named); t != nil {
                if p, _ := t.Underlying().(*Pointer); p != nil {
-                       obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name)
+                       obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name, false)
                        if _, ok := obj.(*Func); ok {
                                return nil, nil, false
                        }
@@ -63,7 +63,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
                }
        }
 
-       obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name)
+       obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false)
 
        // If we didn't find anything and if we have a type parameter with a structural constraint,
        // see if there is a matching field (but not a method, those need to be declared explicitly
@@ -71,7 +71,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
        // are ok here because only fields are accepted as results.
        if obj == nil && isTypeParam(T) {
                if t := structuralType(T); t != nil {
-                       obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name)
+                       obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
                        if _, ok := obj.(*Var); !ok {
                                obj, index, indirect = nil, nil, false // accept fields (variables) only
                        }
@@ -86,9 +86,11 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 //           indirectly via different packages.)
 
 // lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
+// If foldCase is true, the lookup for methods will include looking for any method
+// which case-folds to the same as 'name' (used for giving helpful error messages).
 //
 // The resulting object may not be fully type-checked.
-func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, foldCase bool) (obj Object, index []int, indirect bool) {
        // WARNING: The code in this function is extremely subtle - do not modify casually!
 
        if name == "_" {
@@ -142,7 +144,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 
                                // look for a matching attached method
                                named.resolve(nil)
-                               if i, m := named.lookupMethod(pkg, name); m != nil {
+                               if i, m := named.lookupMethod(pkg, name, foldCase); m != nil {
                                        // potential match
                                        // caution: method may not have a proper signature yet
                                        index = concat(e.index, i)
@@ -189,7 +191,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 
                        case *Interface:
                                // look for a matching method (interface may be a type parameter)
-                               if i, m := t.typeSet().LookupMethod(pkg, name); m != nil {
+                               if i, m := t.typeSet().LookupMethod(pkg, name, foldCase); m != nil {
                                        assert(m.typ != nil)
                                        index = concat(e.index, i)
                                        if obj != nil || e.multiples {
@@ -301,7 +303,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
        if ityp, _ := under(V).(*Interface); ityp != nil {
                // TODO(gri) the methods are sorted - could do this more efficiently
                for _, m := range T.typeSet().methods {
-                       _, f := ityp.typeSet().LookupMethod(m.pkg, m.name)
+                       _, f := ityp.typeSet().LookupMethod(m.pkg, m.name, false)
 
                        if f == nil {
                                if !static {
@@ -331,12 +333,12 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
        // A concrete type implements T if it implements all methods of T.
        for _, m := range T.typeSet().methods {
                // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)?
-               obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name)
+               obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name, false)
 
                // Check if *V implements this method of T.
                if obj == nil {
                        ptr := NewPointer(V)
-                       obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name)
+                       obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name, false)
 
                        if obj != nil {
                                // methods may not have a fully set up signature yet
@@ -502,10 +504,11 @@ func fieldIndex(fields []*Var, pkg *Package, name string) int {
 }
 
 // lookupMethod returns the index of and method with matching package and name, or (-1, nil).
-func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
+// If foldCase is true, method names are considered equal if they are equal with case folding.
+func lookupMethod(methods []*Func, pkg *Package, name string, foldCase bool) (int, *Func) {
        if name != "_" {
                for i, m := range methods {
-                       if m.sameId(pkg, name) {
+                       if (m.name == name || foldCase && strings.EqualFold(m.name, name)) && m.sameId(pkg, m.name) {
                                return i, m
                        }
                }
index 10a2a323a8d03427f589061dec677f1f80db2d35..afe919013d92c0519e923973879960b9956d2d1e 100644 (file)
@@ -41,19 +41,20 @@ func (l *methodList) isLazy() bool {
 // panics if the receiver is lazy.
 func (l *methodList) Add(m *Func) {
        assert(!l.isLazy())
-       if i, _ := lookupMethod(l.methods, m.pkg, m.name); i < 0 {
+       if i, _ := lookupMethod(l.methods, m.pkg, m.name, false); i < 0 {
                l.methods = append(l.methods, m)
        }
 }
 
 // Lookup looks up the method identified by pkg and name in the receiver.
-// Lookup panics if the receiver is lazy.
-func (l *methodList) Lookup(pkg *Package, name string) (int, *Func) {
+// Lookup panics if the receiver is lazy. If foldCase is true, method names
+// are considered equal if they are equal with case folding.
+func (l *methodList) Lookup(pkg *Package, name string, foldCase bool) (int, *Func) {
        assert(!l.isLazy())
        if l == nil {
                return -1, nil
        }
-       return lookupMethod(l.methods, pkg, name)
+       return lookupMethod(l.methods, pkg, name, foldCase)
 }
 
 // Len returns the length of the method list.
index 28db26014f34de3b651577d555d8979686387003..5e84c39776ccb48bab4b07da7fe3856a04f74b12 100644 (file)
@@ -299,12 +299,12 @@ func (n *Named) setUnderlying(typ Type) {
        }
 }
 
-func (n *Named) lookupMethod(pkg *Package, name string) (int, *Func) {
+func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
        n.resolve(nil)
        // If n is an instance, we may not have yet instantiated all of its methods.
        // Look up the method index in orig, and only instantiate method at the
        // matching index (if any).
-       i, _ := n.orig.methods.Lookup(pkg, name)
+       i, _ := n.orig.methods.Lookup(pkg, name, foldCase)
        if i < 0 {
                return -1, nil
        }
index 9f4831e9769334e2d5e62d86d456ff8cfd4e9982..e1f73015b93a738a2e5e0e538d471619fb6baa87 100644 (file)
@@ -56,9 +56,8 @@ func (s *_TypeSet) NumMethods() int { return len(s.methods) }
 func (s *_TypeSet) Method(i int) *Func { return s.methods[i] }
 
 // LookupMethod returns the index of and method with matching package and name, or (-1, nil).
-func (s *_TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) {
-       // TODO(gri) s.methods is sorted - consider binary search
-       return lookupMethod(s.methods, pkg, name)
+func (s *_TypeSet) LookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
+       return lookupMethod(s.methods, pkg, name, foldCase)
 }
 
 func (s *_TypeSet) String() string {