]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: remove MethodSet code - not used by...
authorRobert Griesemer <gri@golang.org>
Sat, 23 Jan 2021 00:59:45 +0000 (16:59 -0800)
committerRobert Griesemer <gri@golang.org>
Sat, 23 Jan 2021 01:57:35 +0000 (01:57 +0000)
We can always re-introduce it if we decide to make use of it.

Change-Id: Ia939fdae978568edc58e21d1af732c6137744aab
Reviewed-on: https://go-review.googlesource.com/c/go/+/285678
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/importer/gcimporter_test.go
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/example_test.go
src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/methodset.go [deleted file]

index a2755244847f42b11d74495172a3bd5e0eaf1fd5..7fb8fed59cf9be1cd00471a1d0854e89d4ed1148 100644 (file)
@@ -384,9 +384,8 @@ func TestCorrectMethodPackage(t *testing.T) {
        }
 
        mutex := imports["sync"].Scope().Lookup("Mutex").(*types2.TypeName).Type()
-       mset := types2.NewMethodSet(types2.NewPointer(mutex)) // methods of *sync.Mutex
-       sel := mset.Lookup(nil, "Lock")
-       lock := sel.Obj().(*types2.Func)
+       obj, _, _ := types2.LookupFieldOrMethod(types2.NewPointer(mutex), false, nil, "Lock")
+       lock := obj.(*types2.Func)
        if got, want := lock.Pkg().Path(), "sync"; got != want {
                t.Errorf("got package path %q; want %q", got, want)
        }
index 5a7ae221e6ebda8b35b72050df2a993815c64629..72a33b50b17f0f053aa64ceb00eda9b5c36124d1 100644 (file)
@@ -685,51 +685,6 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
                        // addressability, should we report the type &(x.typ) instead?
                        check.recordSelection(e, MethodVal, x.typ, obj, index, indirect)
 
-                       // TODO(gri) The verification pass below is disabled for now because
-                       //           method sets don't match method lookup in some cases.
-                       //           For instance, if we made a copy above when creating a
-                       //           custom method for a parameterized received type, the
-                       //           method set method doesn't match (no copy there). There
-                       ///          may be other situations.
-                       disabled := true
-                       if !disabled && debug {
-                               // Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
-                               // TODO(gri) This only works because we call LookupFieldOrMethod
-                               // _before_ calling NewMethodSet: LookupFieldOrMethod completes
-                               // any incomplete interfaces so they are available to NewMethodSet
-                               // (which assumes that interfaces have been completed already).
-                               typ := x.typ
-                               if x.mode == variable {
-                                       // If typ is not an (unnamed) pointer or an interface,
-                                       // use *typ instead, because the method set of *typ
-                                       // includes the methods of typ.
-                                       // Variables are addressable, so we can always take their
-                                       // address.
-                                       if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) {
-                                               typ = &Pointer{base: typ}
-                                       }
-                               }
-                               // If we created a synthetic pointer type above, we will throw
-                               // away the method set computed here after use.
-                               // TODO(gri) Method set computation should probably always compute
-                               // both, the value and the pointer receiver method set and represent
-                               // them in a single structure.
-                               // TODO(gri) Consider also using a method set cache for the lifetime
-                               // of checker once we rely on MethodSet lookup instead of individual
-                               // lookup.
-                               mset := NewMethodSet(typ)
-                               if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj {
-                                       check.dump("%v: (%s).%v -> %s", posFor(e), typ, obj.name, m)
-                                       check.dump("%s\n", mset)
-                                       // Caution: MethodSets are supposed to be used externally
-                                       // only (after all interface types were completed). It's
-                                       // now possible that we get here incorrectly. Not urgent
-                                       // to fix since we only run this code in debug mode.
-                                       // TODO(gri) fix this eventually.
-                                       panic("method sets and lookup don't agree")
-                               }
-                       }
-
                        x.mode = value
 
                        // remove receiver
index dcdeaca0c0020b939a5ee2ff04aded3dd5def0bf..ffd54fe4591c02feb0b8362141d34d2e7ecc2f23 100644 (file)
@@ -107,61 +107,6 @@ func Unused() { {}; {{ var x int; _ = x }} } // make sure empty block scopes get
        // }
 }
 
-// ExampleMethodSet prints the method sets of various types.
-func ExampleMethodSet() {
-       // Parse a single source file.
-       const input = `
-package temperature
-import "fmt"
-type Celsius float64
-func (c Celsius) String() string  { return fmt.Sprintf("%g°C", c) }
-func (c *Celsius) SetF(f float64) { *c = Celsius(f - 32 / 9 * 5) }
-
-type S struct { I; m int }
-type I interface { m() byte }
-`
-       f, err := parseSrc("celsius.go", input)
-       if err != nil {
-               log.Fatal(err)
-       }
-
-       // Type-check a package consisting of this file.
-       // Type information for the imported packages
-       // comes from $GOROOT/pkg/$GOOS_$GOOARCH/fmt.a.
-       conf := types2.Config{Importer: defaultImporter()}
-       pkg, err := conf.Check("temperature", []*syntax.File{f}, nil)
-       if err != nil {
-               log.Fatal(err)
-       }
-
-       // Print the method sets of Celsius and *Celsius.
-       celsius := pkg.Scope().Lookup("Celsius").Type()
-       for _, t := range []types2.Type{celsius, types2.NewPointer(celsius)} {
-               fmt.Printf("Method set of %s:\n", t)
-               mset := types2.NewMethodSet(t)
-               for i := 0; i < mset.Len(); i++ {
-                       fmt.Println(mset.At(i))
-               }
-               fmt.Println()
-       }
-
-       // Print the method set of S.
-       styp := pkg.Scope().Lookup("S").Type()
-       fmt.Printf("Method set of %s:\n", styp)
-       fmt.Println(types2.NewMethodSet(styp))
-
-       // Output:
-       // Method set of temperature.Celsius:
-       // method (temperature.Celsius) String() string
-       //
-       // Method set of *temperature.Celsius:
-       // method (*temperature.Celsius) SetF(f float64)
-       // method (*temperature.Celsius) String() string
-       //
-       // Method set of temperature.S:
-       // MethodSet {}
-}
-
 // ExampleInfo prints various facts recorded by the type checker in a
 // types2.Info struct: definitions of and references to each named object,
 // and the type, value, and mode of every expression in the package.
index e1e7b5814dc89cf1a0f8c8355c0f39851b51027c..5dfb8bfee71cc83adb0c2720d4da30f8f8138177 100644 (file)
@@ -491,3 +491,22 @@ func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
        }
        return -1, nil
 }
+
+// ptrRecv reports whether the receiver is of the form *T.
+func ptrRecv(f *Func) bool {
+       // If a method's receiver type is set, use that as the source of truth for the receiver.
+       // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty
+       // signature. We may reach here before the signature is fully set up: we must explicitly
+       // check if the receiver is set (we cannot just look for non-nil f.typ).
+       if sig, _ := f.typ.(*Signature); sig != nil && sig.recv != nil {
+               _, isPtr := deref(sig.recv.typ)
+               return isPtr
+       }
+
+       // If a method's type is not set it may be a method/function that is:
+       // 1) client-supplied (via NewFunc with no signature), or
+       // 2) internally created but not yet type-checked.
+       // For case 1) we can't do anything; the client must know what they are doing.
+       // For case 2) we can use the information gathered by the resolver.
+       return f.hasPtrRecv
+}
diff --git a/src/cmd/compile/internal/types2/methodset.go b/src/cmd/compile/internal/types2/methodset.go
deleted file mode 100644 (file)
index eb8f122..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-// UNREVIEWED
-// Copyright 2013 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.
-
-// This file implements method sets.
-
-package types2
-
-import (
-       "bytes"
-       "fmt"
-       "sort"
-)
-
-// A MethodSet is an ordered set of concrete or abstract (interface) methods;
-// a method is a MethodVal selection, and they are ordered by ascending m.Obj().Id().
-// The zero value for a MethodSet is a ready-to-use empty method set.
-type MethodSet struct {
-       list []*Selection
-}
-
-func (s *MethodSet) String() string {
-       if s.Len() == 0 {
-               return "MethodSet {}"
-       }
-
-       // Would like to use strings.Builder but it's not available in Go 1.4.
-       var buf bytes.Buffer
-       fmt.Fprintln(&buf, "MethodSet {")
-       for _, f := range s.list {
-               fmt.Fprintf(&buf, "\t%s\n", f)
-       }
-       fmt.Fprintln(&buf, "}")
-       return buf.String()
-}
-
-// Len returns the number of methods in s.
-func (s *MethodSet) Len() int { return len(s.list) }
-
-// At returns the i'th method in s for 0 <= i < s.Len().
-func (s *MethodSet) At(i int) *Selection { return s.list[i] }
-
-// Lookup returns the method with matching package and name, or nil if not found.
-func (s *MethodSet) Lookup(pkg *Package, name string) *Selection {
-       if s.Len() == 0 {
-               return nil
-       }
-
-       key := Id(pkg, name)
-       i := sort.Search(len(s.list), func(i int) bool {
-               m := s.list[i]
-               return m.obj.Id() >= key
-       })
-       if i < len(s.list) {
-               m := s.list[i]
-               if m.obj.Id() == key {
-                       return m
-               }
-       }
-       return nil
-}
-
-// Shared empty method set.
-var emptyMethodSet MethodSet
-
-// Note: NewMethodSet is intended for external use only as it
-//       requires interfaces to be complete. If may be used
-//       internally if LookupFieldOrMethod completed the same
-//       interfaces beforehand.
-
-// NewMethodSet returns the method set for the given type T.
-// It always returns a non-nil method set, even if it is empty.
-func NewMethodSet(T Type) *MethodSet {
-       // WARNING: The code in this function is extremely subtle - do not modify casually!
-       //          This function and lookupFieldOrMethod should be kept in sync.
-
-       // method set up to the current depth, allocated lazily
-       var base methodSet
-
-       typ, isPtr := deref(T)
-
-       // *typ where typ is an interface has no methods.
-       if isPtr && IsInterface(typ) {
-               return &emptyMethodSet
-       }
-
-       // Start with typ as single entry at shallowest depth.
-       current := []embeddedType{{typ, nil, isPtr, false}}
-
-       // Named types that we have seen already, allocated lazily.
-       // Used to avoid endless searches in case of recursive types.
-       // Since only Named types can be used for recursive types, we
-       // only need to track those.
-       // (If we ever allow type aliases to construct recursive types,
-       // we must use type identity rather than pointer equality for
-       // the map key comparison, as we do in consolidateMultiples.)
-       var seen map[*Named]bool
-
-       // collect methods at current depth
-       for len(current) > 0 {
-               var next []embeddedType // embedded types found at current depth
-
-               // field and method sets at current depth, indexed by names (Id's), and allocated lazily
-               var fset map[string]bool // we only care about the field names
-               var mset methodSet
-
-               for _, e := range current {
-                       typ := e.typ
-
-                       // If we have a named type, we may have associated methods.
-                       // Look for those first.
-                       if named := typ.Named(); named != nil {
-                               if seen[named] {
-                                       // We have seen this type before, at a more shallow depth
-                                       // (note that multiples of this type at the current depth
-                                       // were consolidated before). The type at that depth shadows
-                                       // this same type at the current depth, so we can ignore
-                                       // this one.
-                                       continue
-                               }
-                               if seen == nil {
-                                       seen = make(map[*Named]bool)
-                               }
-                               seen[named] = true
-
-                               mset = mset.add(named.methods, e.index, e.indirect, e.multiples)
-
-                               // continue with underlying type
-                               typ = named.underlying
-                       }
-
-                       switch t := typ.(type) {
-                       case *Struct:
-                               for i, f := range t.fields {
-                                       if fset == nil {
-                                               fset = make(map[string]bool)
-                                       }
-                                       fset[f.Id()] = true
-
-                                       // Embedded fields are always of the form T or *T where
-                                       // T is a type name. If typ appeared multiple times at
-                                       // this depth, f.Type appears multiple times at the next
-                                       // depth.
-                                       if f.embedded {
-                                               typ, isPtr := deref(f.typ)
-                                               // TODO(gri) optimization: ignore types that can't
-                                               // have fields or methods (only Named, Struct, and
-                                               // Interface types need to be considered).
-                                               next = append(next, embeddedType{typ, concat(e.index, i), e.indirect || isPtr, e.multiples})
-                                       }
-                               }
-
-                       case *Interface:
-                               mset = mset.add(t.allMethods, e.index, true, e.multiples)
-                       }
-               }
-
-               // Add methods and collisions at this depth to base if no entries with matching
-               // names exist already.
-               for k, m := range mset {
-                       if _, found := base[k]; !found {
-                               // Fields collide with methods of the same name at this depth.
-                               if fset[k] {
-                                       m = nil // collision
-                               }
-                               if base == nil {
-                                       base = make(methodSet)
-                               }
-                               base[k] = m
-                       }
-               }
-
-               // Add all (remaining) fields at this depth as collisions (since they will
-               // hide any method further down) if no entries with matching names exist already.
-               for k := range fset {
-                       if _, found := base[k]; !found {
-                               if base == nil {
-                                       base = make(methodSet)
-                               }
-                               base[k] = nil // collision
-                       }
-               }
-
-               // It's ok to call consolidateMultiples with a nil *Checker because
-               // MethodSets are not used internally (outside debug mode). When used
-               // externally, interfaces are expected to be completed and then we do
-               // not need a *Checker to complete them when (indirectly) calling
-               // Checker.identical via consolidateMultiples.
-               current = (*Checker)(nil).consolidateMultiples(next)
-       }
-
-       if len(base) == 0 {
-               return &emptyMethodSet
-       }
-
-       // collect methods
-       var list []*Selection
-       for _, m := range base {
-               if m != nil {
-                       m.recv = T
-                       list = append(list, m)
-               }
-       }
-       // sort by unique name
-       sort.Slice(list, func(i, j int) bool {
-               return list[i].obj.Id() < list[j].obj.Id()
-       })
-       return &MethodSet{list}
-}
-
-// A methodSet is a set of methods and name collisions.
-// A collision indicates that multiple methods with the
-// same unique id, or a field with that id appeared.
-type methodSet map[string]*Selection // a nil entry indicates a name collision
-
-// Add adds all functions in list to the method set s.
-// If multiples is set, every function in list appears multiple times
-// and is treated as a collision.
-func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool) methodSet {
-       if len(list) == 0 {
-               return s
-       }
-       if s == nil {
-               s = make(methodSet)
-       }
-       for i, f := range list {
-               key := f.Id()
-               // if f is not in the set, add it
-               if !multiples {
-                       // TODO(gri) A found method may not be added because it's not in the method set
-                       // (!indirect && ptrRecv(f)). A 2nd method on the same level may be in the method
-                       // set and may not collide with the first one, thus leading to a false positive.
-                       // Is that possible? Investigate.
-                       if _, found := s[key]; !found && (indirect || !ptrRecv(f)) {
-                               s[key] = &Selection{MethodVal, nil, f, concat(index, i), indirect}
-                               continue
-                       }
-               }
-               s[key] = nil // collision
-       }
-       return s
-}
-
-// ptrRecv reports whether the receiver is of the form *T.
-func ptrRecv(f *Func) bool {
-       // If a method's receiver type is set, use that as the source of truth for the receiver.
-       // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty
-       // signature. We may reach here before the signature is fully set up: we must explicitly
-       // check if the receiver is set (we cannot just look for non-nil f.typ).
-       if sig, _ := f.typ.(*Signature); sig != nil && sig.recv != nil {
-               _, isPtr := deref(sig.recv.typ)
-               return isPtr
-       }
-
-       // If a method's type is not set it may be a method/function that is:
-       // 1) client-supplied (via NewFunc with no signature), or
-       // 2) internally created but not yet type-checked.
-       // For case 1) we can't do anything; the client must know what they are doing.
-       // For case 2) we can use the information gathered by the resolver.
-       return f.hasPtrRecv
-}