...

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

Documentation: cmd/compile/internal/types2

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

View as plain text