Skip to content

Commit b302b5f

Browse files
committed
[dev.go2go] go/types: don't panic if an embedded type is not an interface
Fixes #39693. Change-Id: I7f2a4dd95edac3365a9b41b66afcd0015b5b836c Reviewed-on: https://go-review.googlesource.com/c/go/+/238858 Reviewed-by: Robert Griesemer <[email protected]>
1 parent 6578030 commit b302b5f

File tree

3 files changed

+35
-6
lines changed

3 files changed

+35
-6
lines changed

src/go/types/check_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ var tests = [][]string{
126126
// TODO(gri) Eliminate the need to enumerate these tests here.
127127
// Should just traverse that directory.
128128
{"fixedbugs/issue39664.go2"},
129+
{"fixedbugs/issue39693.go2"},
129130
}
130131

131132
var fset = token.NewFileSet()

src/go/types/fixedbugs/issue39693.go2

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2020 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
type Number interface {
8+
int /* ERROR int is not an interface */
9+
float64 /* ERROR float64 is not an interface */
10+
}
11+
12+
func Add(type T Number)(a, b T) T {
13+
return a /* ERROR not defined */ + b
14+
}

src/go/types/type.go

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package types
66

77
import (
8+
"fmt"
89
"go/token"
910
"sort"
1011
)
@@ -633,12 +634,19 @@ func (t *Interface) Complete() *Interface {
633634
allTypes := t.types
634635

635636
for _, typ := range t.embeddeds {
636-
typ := typ.Interface()
637-
typ.Complete()
638-
for _, m := range typ.allMethods {
637+
utyp := typ.Under()
638+
etyp := utyp.Interface()
639+
if etyp == nil {
640+
if utyp != Typ[Invalid] {
641+
panic(fmt.Sprintf("%s is not an interface", typ))
642+
}
643+
continue
644+
}
645+
etyp.Complete()
646+
for _, m := range etyp.allMethods {
639647
addMethod(m, false)
640648
}
641-
allTypes = intersect(allTypes, typ.types)
649+
allTypes = intersect(allTypes, etyp.allTypes)
642650
}
643651

644652
for i := 0; i < len(todo); i += 2 {
@@ -795,6 +803,7 @@ func (t *Named) AddMethod(m *Func) {
795803

796804
// A TypeParam represents a type parameter type.
797805
type TypeParam struct {
806+
check *Checker // for lazy type bound completion
798807
id uint64 // unique id
799808
ptr bool // pointer designation
800809
obj *TypeName // corresponding type name
@@ -806,7 +815,7 @@ type TypeParam struct {
806815
// NewTypeParam returns a new TypeParam.
807816
func (check *Checker) NewTypeParam(ptr bool, obj *TypeName, index int, bound Type) *TypeParam {
808817
assert(bound != nil)
809-
typ := &TypeParam{id: check.nextId, ptr: ptr, obj: obj, index: index, bound: bound}
818+
typ := &TypeParam{check: check, id: check.nextId, ptr: ptr, obj: obj, index: index, bound: bound}
810819
check.nextId++
811820
if obj.typ == nil {
812821
obj.typ = typ
@@ -816,7 +825,12 @@ func (check *Checker) NewTypeParam(ptr bool, obj *TypeName, index int, bound Typ
816825

817826
func (t *TypeParam) Bound() *Interface {
818827
iface := t.bound.Interface()
819-
iface.Complete() // TODO(gri) should we use check.completeInterface instead?
828+
// use the type bound position if we have one
829+
pos := token.NoPos
830+
if n, _ := t.bound.(*Named); n != nil {
831+
pos = n.obj.pos
832+
}
833+
t.check.completeInterface(pos, iface)
820834
return iface
821835
}
822836

0 commit comments

Comments
 (0)