1 // Copyright 2021 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.
9 "go/internal/typeparams"
13 func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
15 var tname *ast.Ident // "type" name of first entry in a type list declaration
17 addEmbedded := func(pos token.Pos, typ Type) {
18 ityp.embeddeds = append(ityp.embeddeds, typ)
19 if ityp.embedPos == nil {
20 ityp.embedPos = new([]token.Pos)
22 *ityp.embedPos = append(*ityp.embedPos, pos)
25 for _, f := range iface.Methods.List {
26 if len(f.Names) == 0 {
27 // We have an embedded type; possibly a union of types.
28 addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type)))
32 // We have a method with name f.Names[0], or a type
33 // of a type list (name.Name == "type").
34 // (The parser ensures that there's only one method
35 // and we don't care if a constructed AST has more.)
38 check.errorf(name, _BlankIfaceMethod, "invalid method name _")
42 // TODO(rfindley) Remove type list handling once the parser doesn't accept type lists anymore.
43 if name.Name == "type" {
44 // Report an error for the first type list per interface
45 // if we don't allow type lists, but continue.
46 if !allowTypeLists && tlist == nil {
47 check.softErrorf(name, _Todo, "use generalized embedding syntax instead of a type list")
49 // For now, collect all type list entries as if it
50 // were a single union, where each union element is
52 // TODO(rfindley) remove once we disallow type lists
53 op := new(ast.UnaryExpr)
56 tlist = append(tlist, op)
57 // Report an error if we have multiple type lists in an
58 // interface, but only if they are permitted in the first place.
59 if allowTypeLists && tname != nil && tname != name {
60 check.errorf(name, _Todo, "cannot have multiple type lists in an interface")
66 typ := check.typ(f.Type)
67 sig, _ := typ.(*Signature)
69 if typ != Typ[Invalid] {
70 check.invalidAST(f.Type, "%s is not a method signature", typ)
75 // Always type-check method type parameters but complain if they are not enabled.
76 // (This extra check is needed here because interface method signatures don't have
77 // a receiver specification.)
78 if sig.tparams != nil {
79 var at positioner = f.Type
80 if tparams := typeparams.Get(f.Type); tparams != nil {
83 check.errorf(at, _Todo, "methods cannot have type parameters")
86 // use named receiver type if available (for better error messages)
87 var recvTyp Type = ityp
91 sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp)
93 m := NewFunc(name.Pos(), check.pkg, name.Name, sig)
94 check.recordDef(name, m)
95 ityp.methods = append(ityp.methods, m)
100 // TODO(rfindley): this differs from types2 due to the use of Pos() below,
101 // which should actually be on the ~. Confirm that this position is correct.
102 addEmbedded(tlist[0].Pos(), parseUnion(check, tlist))
105 // All methods and embedded elements for this interface are collected;
106 // i.e., this interface is may be used in a type set computation.
109 if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 {
111 ityp.tset = &topTypeSet
115 // sort for API stability
116 sortMethods(ityp.methods)
117 // (don't sort embeddeds: they must correspond to *embedPos entries)
119 // Compute type set with a non-nil *Checker as soon as possible
120 // to report any errors. Subsequent uses of type sets should be
121 // using this computed type set and won't need to pass in a *Checker.
122 check.later(func() { computeTypeSet(check, iface.Pos(), ityp) })
125 func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr {
126 if o, _ := x.(*ast.BinaryExpr); o != nil && o.Op == token.OR {
127 list = flattenUnion(list, o.X)
130 return append(list, x)