diff --git a/go/extractor/extractor.go b/go/extractor/extractor.go index c157f7c8f672..936e0b6fdec8 100644 --- a/go/extractor/extractor.go +++ b/go/extractor/extractor.go @@ -518,6 +518,7 @@ func extractMethod(tw *trap.Writer, meth *types.Func) trap.Label { // For more information on objects, see: // https://github.com/golang/example/blob/master/gotypes/README.md#objects func extractObject(tw *trap.Writer, obj types.Object, lbl trap.Label) { + checkObjectNotSpecialized(obj) name := obj.Name() isBuiltin := obj.Parent() == types.Universe var kind int @@ -1637,7 +1638,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label { // Note that methods coming from embedded interfaces can be // accessed through `Method(i)`, so there is no need to // deal with them separately. - meth := tp.Method(i) + meth := tp.Method(i).Origin() // Note that methods do not have a parent scope, so they are // not dealt with by `extractScopes` @@ -1707,7 +1708,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label { // ensure all methods have labels - note that methods do not have a // parent scope, so they are not dealt with by `extractScopes` for i := 0; i < origintp.NumMethods(); i++ { - meth := origintp.Method(i) + meth := origintp.Method(i).Origin() extractMethod(tw, meth) } @@ -1715,7 +1716,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label { // associate all methods of underlying interface with this type if underlyingInterface, ok := underlying.(*types.Interface); ok { for i := 0; i < underlyingInterface.NumMethods(); i++ { - methlbl := extractMethod(tw, underlyingInterface.Method(i)) + methlbl := extractMethod(tw, underlyingInterface.Method(i).Origin()) dbscheme.MethodHostsTable.Emit(tw, methlbl, lbl) } } @@ -1787,7 +1788,7 @@ func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) { case *types.Interface: var b strings.Builder for i := 0; i < tp.NumMethods(); i++ { - meth := tp.Method(i) + meth := tp.Method(i).Origin() methLbl := extractType(tw, meth.Type()) if i > 0 { b.WriteString(",") @@ -2143,3 +2144,20 @@ func skipExtractingValueForLeftOperand(tw *trap.Writer, be *ast.BinaryExpr) bool } return true } + +// checkObjectNotSpecialized exits the program if `obj` is specialized. Note +// that specialization is only possible for function objects and variable +// objects. +func checkObjectNotSpecialized(obj types.Object) { + if funcObj, ok := obj.(*types.Func); ok && funcObj != funcObj.Origin() { + log.Fatalf("Encountered unexpected specialization %s of generic function object %s", funcObj.FullName(), funcObj.Origin().FullName()) + } + if varObj, ok := obj.(*types.Var); ok && varObj != varObj.Origin() { + log.Fatalf("Encountered unexpected specialization %s of generic variable object %s", varObj.String(), varObj.Origin().String()) + } + if typeNameObj, ok := obj.(*types.TypeName); ok { + if namedType, ok := typeNameObj.Type().(*types.Named); ok && namedType != namedType.Origin() { + log.Fatalf("Encountered type object for specialization %s of named type %s", namedType.String(), namedType.Origin().String()) + } + } +}