t.Errorf("expected full parse, stopped at %q", p.lit)
}
+ // interfaces must be explicitly completed
+ if ityp, _ := typ.(*types.Interface); ityp != nil {
+ ityp.Complete()
+ }
+
got := typ.String()
if got != test.want {
t.Errorf("got type %q, expected %q", got, test.want)
case _Panic:
// panic(x)
- T := new(Interface)
- check.assignment(x, T, "argument to panic")
+ check.assignment(x, &emptyInterface, "argument to panic")
if x.mode == invalid {
return
}
x.mode = novalue
if check.Types != nil {
- check.recordBuiltinType(call.Fun, makeSig(nil, T))
+ check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
}
case _Print, _Println:
case _Recover:
// recover() interface{}
x.mode = value
- x.typ = new(Interface)
+ x.typ = &emptyInterface
if check.Types != nil {
check.recordBuiltinType(call.Fun, makeSig(x.typ))
}
{NewTypeName(0, nil, "t0", nil), false}, // no type yet
{NewTypeName(0, pkg, "t0", nil), false}, // no type yet
{t1, false}, // type name refers to named type and vice versa
- {NewTypeName(0, nil, "t2", new(Interface)), true}, // type name refers to unnamed type
- {NewTypeName(0, pkg, "t3", n1), true}, // type name refers to named type with different type name
- {NewTypeName(0, nil, "t4", Typ[Int32]), true}, // type name refers to basic type with different name
- {NewTypeName(0, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name
- {NewTypeName(0, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe)
- {NewTypeName(0, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already
+ {NewTypeName(0, nil, "t2", &emptyInterface), true}, // type name refers to unnamed type
+ {NewTypeName(0, pkg, "t3", n1), true}, // type name refers to named type with different type name
+ {NewTypeName(0, nil, "t4", Typ[Int32]), true}, // type name refers to basic type with different name
+ {NewTypeName(0, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name
+ {NewTypeName(0, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe)
+ {NewTypeName(0, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already
} {
check(test.name, test.alias)
}
type Event interface {
Target() Element
}
+
+// Recognize issue #13895.
+
+type (
+ _ interface{ m(B1) }
+ A1 interface{ a(D1) }
+ B1 interface{ A1 }
+ C1 interface{ B1 /* ERROR issue #18395 */ }
+ D1 interface{ C1 }
+)
+
+var _ A1 = C1 /* ERROR cannot use C1 */ (nil)
\ No newline at end of file
allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
}
-// NewInterface returns a new interface for the given methods and embedded types.
+// emptyInterface represents the empty (completed) interface
+var emptyInterface = Interface{allMethods: markComplete}
+
+// markComplete is used to mark an empty interface as completely
+// set up by setting the allMethods field to a non-nil empty slice.
+var markComplete = make([]*Func, 0)
+
+// NewInterface returns a new (incomplete) interface for the given methods and embedded types.
+// To compute the method set of the interface, Complete must be called.
func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
typ := new(Interface)
+ if len(methods) == 0 && len(embeddeds) == 0 {
+ return typ
+ }
+
var mset objset
for _, m := range methods {
if mset.insert(m) != nil {
// }
//
buf.WriteString("interface{")
+ empty := true
if gcCompatibilityMode {
// print flattened interface
// (useful to compare against gc-generated interfaces)
}
buf.WriteString(m.name)
writeSignature(buf, m.typ.(*Signature), qf, visited)
+ empty = false
}
} else {
// print explicit interface methods and embedded types
}
buf.WriteString(m.name)
writeSignature(buf, m.typ.(*Signature), qf, visited)
+ empty = false
}
for i, typ := range t.embeddeds {
if i > 0 || len(t.methods) > 0 {
buf.WriteString("; ")
}
writeType(buf, typ, qf, visited)
+ empty = false
}
}
+ if t.allMethods == nil || len(t.methods) > len(t.allMethods) {
+ if !empty {
+ buf.WriteByte(' ')
+ }
+ buf.WriteString("/* incomplete */")
+ }
buf.WriteByte('}')
case *Map:
}
}
+func TestIncompleteInterfaces(t *testing.T) {
+ sig := NewSignature(nil, nil, nil, false)
+ for _, test := range []struct {
+ typ *Interface
+ want string
+ }{
+ {new(Interface), "interface{/* incomplete */}"},
+ {new(Interface).Complete(), "interface{}"},
+ {NewInterface(nil, nil), "interface{/* incomplete */}"},
+ {NewInterface(nil, nil).Complete(), "interface{}"},
+ {NewInterface([]*Func{NewFunc(token.NoPos, nil, "m", sig)}, nil), "interface{m() /* incomplete */}"},
+ {NewInterface([]*Func{NewFunc(token.NoPos, nil, "m", sig)}, nil).Complete(), "interface{m()}"},
+ } {
+ got := test.typ.String()
+ if got != test.want {
+ t.Errorf("got: %s, want: %s", got, test.want)
+ }
+ }
+}
+
func TestQualifiedTypeString(t *testing.T) {
p, _ := pkgFor("p.go", "package p; type T int", nil)
q, _ := pkgFor("q.go", "package q", nil)
}
iface.embeddeds = append(iface.embeddeds, named)
// collect embedded methods
- if debug && embed.allMethods == nil {
- check.dump("%s: incomplete embedded interface %s", pos, named)
- unreachable()
+ if embed.allMethods == nil {
+ check.errorf(pos, "internal error: incomplete embedded interface %s (issue #18395)", named)
}
for _, m := range embed.allMethods {
if check.declareInSet(&mset, pos, m) {