]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: add debugging code to detect use of incomplete interfaces
authorRobert Griesemer <gri@golang.org>
Tue, 21 Nov 2017 05:54:41 +0000 (21:54 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 27 Nov 2017 16:47:51 +0000 (16:47 +0000)
The comment for phase 2 of checker.interfaceType (typexpr.go:517)
requires that embedded interfaces be complete for correctness of
the algorithm.

Yet, the very next comment (typexpr.go:530) states that underlying
embedded interfaces may in fact be incomplete.

This is in fact the case and the underlying bug in issue #18395.

This change makes sure that new interface types are marked complete
when finished (per the implicit definition in Interface.Complete,
type.go:302). It also adds a check, enabled in debug mode only, to
detect the use of incomplete embedded interfaces during construction
of a new interface. In debug mode, this check fails for the testcase
in the issue (and several others).

This change has no noticeable impact with debug mode disabled.

For #18395.

Change-Id: Ibb81e47257651282fb3755a80a36ab5d392e636d
Reviewed-on: https://go-review.googlesource.com/78955
Reviewed-by: Alan Donovan <adonovan@google.com>
src/go/types/typexpr.go

index 2272ac06450581ac849632c28cfc3e29181d655e..d48dcbffc3f8a6b10626325c3201b950b795528f 100644 (file)
@@ -540,6 +540,10 @@ func (check *Checker) interfaceType(iface *Interface, ityp *ast.InterfaceType, d
                }
                iface.embeddeds = append(iface.embeddeds, named)
                // collect embedded methods
+               if debug && embed.allMethods == nil {
+                       check.dump("%s: incomplete embedded interface %s", pos, named)
+                       unreachable()
+               }
                for _, m := range embed.allMethods {
                        if check.declareInSet(&mset, pos, m) {
                                iface.allMethods = append(iface.allMethods, m)
@@ -579,7 +583,11 @@ func (check *Checker) interfaceType(iface *Interface, ityp *ast.InterfaceType, d
        // claim source order in the future. Revisit.
        sort.Sort(byUniqueTypeName(iface.embeddeds))
 
-       sort.Sort(byUniqueMethodName(iface.allMethods))
+       if iface.allMethods == nil {
+               iface.allMethods = make([]*Func, 0) // mark interface as complete
+       } else {
+               sort.Sort(byUniqueMethodName(iface.allMethods))
+       }
 }
 
 // byUniqueTypeName named type lists can be sorted by their unique type names.