Source file src/cmd/compile/internal/types2/interface.go

     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.
     4  
     5  package types2
     6  
     7  import "cmd/compile/internal/syntax"
     8  
     9  // ----------------------------------------------------------------------------
    10  // API
    11  
    12  // An Interface represents an interface type.
    13  type Interface struct {
    14  	check     *Checker      // for error reporting; nil once type set is computed
    15  	obj       *TypeName     // corresponding declared object; or nil (for better error messages)
    16  	methods   []*Func       // ordered list of explicitly declared methods
    17  	embeddeds []Type        // ordered list of explicitly embedded elements
    18  	embedPos  *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space
    19  	implicit  bool          // interface is wrapper for type set literal (non-interface T, ~T, or A|B)
    20  	complete  bool          // indicates that all fields (except for tset) are set up
    21  
    22  	tset *_TypeSet // type set described by this interface, computed lazily
    23  }
    24  
    25  // typeSet returns the type set for interface t.
    26  func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(t.check, nopos, t) }
    27  
    28  // emptyInterface represents the empty interface
    29  var emptyInterface = Interface{complete: true, tset: &topTypeSet}
    30  
    31  // NewInterfaceType returns a new interface for the given methods and embedded types.
    32  // NewInterfaceType takes ownership of the provided methods and may modify their types
    33  // by setting missing receivers.
    34  func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
    35  	if len(methods) == 0 && len(embeddeds) == 0 {
    36  		return &emptyInterface
    37  	}
    38  
    39  	// set method receivers if necessary
    40  	typ := (*Checker)(nil).newInterface()
    41  	for _, m := range methods {
    42  		if sig := m.typ.(*Signature); sig.recv == nil {
    43  			sig.recv = NewVar(m.pos, m.pkg, "", typ)
    44  		}
    45  	}
    46  
    47  	// sort for API stability
    48  	sortMethods(methods)
    49  
    50  	typ.methods = methods
    51  	typ.embeddeds = embeddeds
    52  	typ.complete = true
    53  
    54  	return typ
    55  }
    56  
    57  // check may be nil
    58  func (check *Checker) newInterface() *Interface {
    59  	typ := &Interface{check: check}
    60  	if check != nil {
    61  		check.needsCleanup(typ)
    62  	}
    63  	return typ
    64  }
    65  
    66  // MarkImplicit marks the interface t as implicit, meaning this interface
    67  // corresponds to a constraint literal such as ~T or A|B without explicit
    68  // interface embedding. MarkImplicit should be called before any concurrent use
    69  // of implicit interfaces.
    70  func (t *Interface) MarkImplicit() {
    71  	t.implicit = true
    72  }
    73  
    74  // NumExplicitMethods returns the number of explicitly declared methods of interface t.
    75  func (t *Interface) NumExplicitMethods() int { return len(t.methods) }
    76  
    77  // ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods().
    78  // The methods are ordered by their unique Id.
    79  func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] }
    80  
    81  // NumEmbeddeds returns the number of embedded types in interface t.
    82  func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) }
    83  
    84  // EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds().
    85  func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] }
    86  
    87  // NumMethods returns the total number of methods of interface t.
    88  func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() }
    89  
    90  // Method returns the i'th method of interface t for 0 <= i < t.NumMethods().
    91  // The methods are ordered by their unique Id.
    92  func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) }
    93  
    94  // Empty reports whether t is the empty interface.
    95  func (t *Interface) Empty() bool { return t.typeSet().IsAll() }
    96  
    97  // IsComparable reports whether each type in interface t's type set is comparable.
    98  func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable(nil) }
    99  
   100  // IsMethodSet reports whether the interface t is fully described by its method set.
   101  func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() }
   102  
   103  // IsImplicit reports whether the interface t is a wrapper for a type set literal.
   104  func (t *Interface) IsImplicit() bool { return t.implicit }
   105  
   106  func (t *Interface) Underlying() Type { return t }
   107  func (t *Interface) String() string   { return TypeString(t, nil) }
   108  
   109  // ----------------------------------------------------------------------------
   110  // Implementation
   111  
   112  func (t *Interface) cleanup() {
   113  	t.check = nil
   114  	t.embedPos = nil
   115  }
   116  
   117  func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) {
   118  	addEmbedded := func(pos syntax.Pos, typ Type) {
   119  		ityp.embeddeds = append(ityp.embeddeds, typ)
   120  		if ityp.embedPos == nil {
   121  			ityp.embedPos = new([]syntax.Pos)
   122  		}
   123  		*ityp.embedPos = append(*ityp.embedPos, pos)
   124  	}
   125  
   126  	for _, f := range iface.MethodList {
   127  		if f.Name == nil {
   128  			addEmbedded(posFor(f.Type), parseUnion(check, f.Type))
   129  			continue
   130  		}
   131  		// f.Name != nil
   132  
   133  		// We have a method with name f.Name.
   134  		name := f.Name.Value
   135  		if name == "_" {
   136  			if check.conf.CompilerErrorMessages {
   137  				check.error(f.Name, "methods must have a unique non-blank name")
   138  			} else {
   139  				check.error(f.Name, "invalid method name _")
   140  			}
   141  			continue // ignore
   142  		}
   143  
   144  		typ := check.typ(f.Type)
   145  		sig, _ := typ.(*Signature)
   146  		if sig == nil {
   147  			if typ != Typ[Invalid] {
   148  				check.errorf(f.Type, invalidAST+"%s is not a method signature", typ)
   149  			}
   150  			continue // ignore
   151  		}
   152  
   153  		// use named receiver type if available (for better error messages)
   154  		var recvTyp Type = ityp
   155  		if def != nil {
   156  			recvTyp = def
   157  		}
   158  		sig.recv = NewVar(f.Name.Pos(), check.pkg, "", recvTyp)
   159  
   160  		m := NewFunc(f.Name.Pos(), check.pkg, name, sig)
   161  		check.recordDef(f.Name, m)
   162  		ityp.methods = append(ityp.methods, m)
   163  	}
   164  
   165  	// All methods and embedded elements for this interface are collected;
   166  	// i.e., this interface may be used in a type set computation.
   167  	ityp.complete = true
   168  
   169  	if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 {
   170  		// empty interface
   171  		ityp.tset = &topTypeSet
   172  		return
   173  	}
   174  
   175  	// sort for API stability
   176  	// (don't sort embeddeds: they must correspond to *embedPos entries)
   177  	sortMethods(ityp.methods)
   178  
   179  	// Compute type set as soon as possible to report any errors.
   180  	// Subsequent uses of type sets will use this computed type
   181  	// set and won't need to pass in a *Checker.
   182  	check.later(func() {
   183  		computeInterfaceTypeSet(check, iface.Pos(), ityp)
   184  	}).describef(iface, "compute type set for %s", ityp)
   185  }
   186  

View as plain text