]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: re-use existing code for Interface...
authorRobert Griesemer <gri@golang.org>
Fri, 21 May 2021 04:24:36 +0000 (21:24 -0700)
committerRobert Griesemer <gri@golang.org>
Mon, 24 May 2021 23:15:35 +0000 (23:15 +0000)
Change-Id: I0fa07e49651aa086c2edbd1162332608c400250f
Reviewed-on: https://go-review.googlesource.com/c/go/+/321751
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/interface.go
src/cmd/compile/internal/types2/type.go

index bbd25cbd094e627f8c0836c98807eec357f0aff3..21968b34aa7a220b21dbbdc277915eab6c4d6d94 100644 (file)
@@ -6,6 +6,7 @@ package types2
 
 import (
        "cmd/compile/internal/syntax"
+       "fmt"
        "sort"
 )
 
@@ -139,7 +140,13 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) {
                panic("internal error: incomplete interface")
        }
 
-       if check.conf.Trace {
+       completeInterface(check, pos, ityp)
+}
+
+func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) {
+       assert(ityp.allMethods == nil)
+
+       if check != nil && check.conf.Trace {
                // Types don't generally have position information.
                // If we don't have a valid pos provided, try to use
                // one close enough.
@@ -175,6 +182,7 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) {
        // we can get rid of the mpos map below and simply use the cloned method's
        // position.
 
+       var todo []*Func
        var seen objset
        var methods []*Func
        mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages
@@ -184,6 +192,9 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) {
                        methods = append(methods, m)
                        mpos[m] = pos
                case explicit:
+                       if check == nil {
+                               panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name))
+                       }
                        var err error_
                        err.errorf(pos, "duplicate method %s", m.name)
                        err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name)
@@ -194,6 +205,11 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) {
                        // If we're pre-go1.14 (overlapping embeddings are not permitted), report that
                        // error here as well (even though we could do it eagerly) because it's the same
                        // error message.
+                       if check == nil {
+                               // check method signatures after all locally embedded interfaces are computed
+                               todo = append(todo, m, other.(*Func))
+                               break
+                       }
                        check.later(func() {
                                if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) {
                                        var err error_
@@ -212,9 +228,15 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) {
        // collect types
        allTypes := ityp.types
 
-       posList := check.posMap[ityp]
+       var posList []syntax.Pos
+       if check != nil {
+               posList = check.posMap[ityp]
+       }
        for i, typ := range ityp.embeddeds {
-               pos := posList[i] // embedding position
+               var pos syntax.Pos // embedding position
+               if posList != nil {
+                       pos = posList[i]
+               }
                utyp := under(typ)
                etyp := asInterface(utyp)
                if etyp == nil {
@@ -225,17 +247,32 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) {
                                } else {
                                        format = "%s is not an interface"
                                }
-                               check.errorf(pos, format, typ)
+                               if check != nil {
+                                       check.errorf(pos, format, typ)
+                               } else {
+                                       panic(fmt.Sprintf("%s: "+format, pos, typ))
+                               }
                        }
                        continue
                }
-               check.completeInterface(pos, etyp)
+               if etyp.allMethods == nil {
+                       completeInterface(check, pos, etyp)
+               }
                for _, m := range etyp.allMethods {
                        addMethod(pos, m, false) // use embedding position pos rather than m.pos
                }
                allTypes = intersect(allTypes, etyp.allTypes)
        }
 
+       // process todo's (this only happens if check == nil)
+       for i := 0; i < len(todo); i += 2 {
+               m := todo[i]
+               other := todo[i+1]
+               if !Identical(m.typ, other.typ) {
+                       panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name))
+               }
+       }
+
        if methods != nil {
                sortMethods(methods)
                ityp.allMethods = methods
index 55c2f336ce8dfe2d720524795aa5c75e923eb1bc..db955a8509dc276c9e687cb06151f4df65103e9c 100644 (file)
@@ -6,7 +6,6 @@ package types2
 
 import (
        "cmd/compile/internal/syntax"
-       "fmt"
        "sync/atomic"
 )
 
@@ -544,64 +543,9 @@ func (t *Interface) isSatisfiedBy(typ Type) bool {
 // 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
-       }
-
-       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)
-       }
-
-       allTypes := t.types
-
-       for _, typ := range t.embeddeds {
-               utyp := under(typ)
-               etyp := asInterface(utyp)
-               if etyp == nil {
-                       if utyp != Typ[Invalid] {
-                               panic(fmt.Sprintf("%s is not an interface", typ))
-                       }
-                       continue
-               }
-               etyp.Complete()
-               for _, m := range etyp.allMethods {
-                       addMethod(m, false)
-               }
-               allTypes = intersect(allTypes, etyp.allTypes)
-       }
-
-       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)
-               }
-       }
-
-       if methods != nil {
-               sortMethods(methods)
-               t.allMethods = methods
+       if t.allMethods == nil {
+               completeInterface(nil, nopos, t)
        }
-       t.allTypes = allTypes
-
        return t
 }