]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libgo/go/go/types/type.go
libgo: update to Go1.14beta1
[thirdparty/gcc.git] / libgo / go / go / types / type.go
index 3dd9eb97f5c0c01220f87463edf3a8c902cf34e4..087cda429d689ab83c714a5f18caef0fdd442e16 100644 (file)
@@ -278,37 +278,32 @@ func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
 // NewInterfaceType takes ownership of the provided methods and may modify their types by setting
 // missing receivers. To compute the method set of the interface, Complete must be called.
 func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
-       typ := new(Interface)
-
        if len(methods) == 0 && len(embeddeds) == 0 {
-               return typ
+               return &emptyInterface
        }
 
-       var mset objset
+       // set method receivers if necessary
+       typ := new(Interface)
        for _, m := range methods {
-               if mset.insert(m) != nil {
-                       panic("multiple methods with the same name")
-               }
-               // set receiver if we don't have one
                if sig := m.typ.(*Signature); sig.recv == nil {
                        sig.recv = NewVar(m.pos, m.pkg, "", typ)
                }
        }
-       sort.Sort(byUniqueMethodName(methods))
 
-       if len(embeddeds) > 0 {
-               // All embedded types should be interfaces; however, defined types
-               // may not yet be fully resolved. Only verify that non-defined types
-               // are interfaces. This matches the behavior of the code before the
-               // fix for #25301 (issue #25596).
-               for _, t := range embeddeds {
-                       if _, ok := t.(*Named); !ok && !IsInterface(t) {
-                               panic("embedded type is not an interface")
-                       }
+       // All embedded types should be interfaces; however, defined types
+       // may not yet be fully resolved. Only verify that non-defined types
+       // are interfaces. This matches the behavior of the code before the
+       // fix for #25301 (issue #25596).
+       for _, t := range embeddeds {
+               if _, ok := t.(*Named); !ok && !IsInterface(t) {
+                       panic("embedded type is not an interface")
                }
-               sort.Stable(byUniqueTypeName(embeddeds))
        }
 
+       // sort for API stability
+       sort.Sort(byUniqueMethodName(methods))
+       sort.Stable(byUniqueTypeName(embeddeds))
+
        typ.methods = methods
        typ.embeddeds = embeddeds
        return typ
@@ -334,40 +329,76 @@ func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named)
 func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] }
 
 // NumMethods returns the total number of methods of interface t.
-func (t *Interface) NumMethods() int { return len(t.allMethods) }
+// The interface must have been completed.
+func (t *Interface) NumMethods() int { t.assertCompleteness(); return len(t.allMethods) }
+
+func (t *Interface) assertCompleteness() {
+       if t.allMethods == nil {
+               panic("interface is incomplete")
+       }
+}
 
 // Method returns the i'th method of interface t for 0 <= i < t.NumMethods().
 // The methods are ordered by their unique Id.
-func (t *Interface) Method(i int) *Func { return t.allMethods[i] }
+// The interface must have been completed.
+func (t *Interface) Method(i int) *Func { t.assertCompleteness(); return t.allMethods[i] }
 
 // Empty reports whether t is the empty interface.
-func (t *Interface) Empty() bool { return len(t.allMethods) == 0 }
+// The interface must have been completed.
+func (t *Interface) Empty() bool { t.assertCompleteness(); return len(t.allMethods) == 0 }
 
 // Complete computes the interface's method set. It must be called by users of
 // NewInterfaceType and NewInterface after the interface's embedded types are
 // fully defined and before using the interface type in any way other than to
-// form other types. Complete returns the receiver.
+// form other types. The interface must not contain duplicate methods or a
+// panic occurs. Complete returns the receiver.
 func (t *Interface) Complete() *Interface {
+       // TODO(gri) consolidate this method with Checker.completeInterface
        if t.allMethods != nil {
                return t
        }
 
-       // collect all methods
-       var allMethods []*Func
-       allMethods = append(allMethods, t.methods...)
-       for _, et := range t.embeddeds {
-               it := et.Underlying().(*Interface)
-               it.Complete()
-               // copy embedded methods unchanged (see issue #28282)
-               allMethods = append(allMethods, it.allMethods...)
+       t.allMethods = markComplete // avoid infinite recursion
+
+       var todo []*Func
+       var methods []*Func
+       var seen objset
+       addMethod := func(m *Func, explicit bool) {
+               switch other := seen.insert(m); {
+               case other == nil:
+                       methods = append(methods, m)
+               case explicit:
+                       panic("duplicate method " + m.name)
+               default:
+                       // check method signatures after all locally embedded interfaces are computed
+                       todo = append(todo, m, other.(*Func))
+               }
+       }
+
+       for _, m := range t.methods {
+               addMethod(m, true)
+       }
+
+       for _, typ := range t.embeddeds {
+               typ := typ.Underlying().(*Interface)
+               typ.Complete()
+               for _, m := range typ.allMethods {
+                       addMethod(m, false)
+               }
+       }
+
+       for i := 0; i < len(todo); i += 2 {
+               m := todo[i]
+               other := todo[i+1]
+               if !Identical(m.typ, other.typ) {
+                       panic("duplicate method " + m.name)
+               }
        }
-       sort.Sort(byUniqueMethodName(allMethods))
 
-       // t.methods and/or t.embeddeds may have been empty
-       if allMethods == nil {
-               allMethods = markComplete
+       if methods != nil {
+               sort.Sort(byUniqueMethodName(methods))
+               t.allMethods = methods
        }
-       t.allMethods = allMethods
 
        return t
 }
@@ -417,7 +448,9 @@ func (c *Chan) Elem() Type { return c.elem }
 
 // A Named represents a named type.
 type Named struct {
+       info       typeInfo  // for cycle detection
        obj        *TypeName // corresponding declared object
+       orig       Type      // type (on RHS of declaration) this *Named type is derived of (for cycle reporting)
        underlying Type      // possibly a *Named during setup; never a *Named once set up completely
        methods    []*Func   // methods declared for this type (not the method set of this type); signatures are type-checked lazily
 }
@@ -429,7 +462,7 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
        if _, ok := underlying.(*Named); ok {
                panic("types.NewNamed: underlying type must not be *Named")
        }
-       typ := &Named{obj: obj, underlying: underlying, methods: methods}
+       typ := &Named{obj: obj, orig: underlying, underlying: underlying, methods: methods}
        if obj.typ == nil {
                obj.typ = typ
        }