Source file src/go/types/selection.go

     1  // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
     2  // Source: ../../cmd/compile/internal/types2/selection.go
     3  
     4  // Copyright 2013 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  
     8  // This file implements Selections.
     9  
    10  package types
    11  
    12  import (
    13  	"bytes"
    14  	"fmt"
    15  )
    16  
    17  // SelectionKind describes the kind of a selector expression x.f
    18  // (excluding qualified identifiers).
    19  //
    20  // If x is a struct or *struct, a selector expression x.f may denote a
    21  // sequence of selection operations x.a.b.c.f. The SelectionKind
    22  // describes the kind of the final (explicit) operation; all the
    23  // previous (implicit) operations are always field selections.
    24  // Each element of Indices specifies an implicit field (a, b, c)
    25  // by its index in the struct type of the field selection operand.
    26  //
    27  // For a FieldVal operation, the final selection refers to the field
    28  // specified by Selection.Obj.
    29  //
    30  // For a MethodVal operation, the final selection refers to a method.
    31  // If the "pointerness" of the method's declared receiver does not
    32  // match that of the effective receiver after implicit field
    33  // selection, then an & or * operation is implicitly applied to the
    34  // receiver variable or value.
    35  // So, x.f denotes (&x.a.b.c).f when f requires a pointer receiver but
    36  // x.a.b.c is a non-pointer variable; and it denotes (*x.a.b.c).f when
    37  // f requires a non-pointer receiver but x.a.b.c is a pointer value.
    38  //
    39  // All pointer indirections, whether due to implicit or explicit field
    40  // selections or * operations inserted for "pointerness", panic if
    41  // applied to a nil pointer, so a method call x.f() may panic even
    42  // before the function call.
    43  //
    44  // By contrast, a MethodExpr operation T.f is essentially equivalent
    45  // to a function literal of the form:
    46  //
    47  //	func(x T, args) (results) { return x.f(args) }
    48  //
    49  // Consequently, any implicit field selections and * operations
    50  // inserted for "pointerness" are not evaluated until the function is
    51  // called, so a T.f or (*T).f expression never panics.
    52  type SelectionKind int
    53  
    54  const (
    55  	FieldVal   SelectionKind = iota // x.f is a struct field selector
    56  	MethodVal                       // x.f is a method selector
    57  	MethodExpr                      // x.f is a method expression
    58  )
    59  
    60  // A Selection describes a selector expression x.f.
    61  // For the declarations:
    62  //
    63  //	type T struct{ x int; E }
    64  //	type E struct{}
    65  //	func (e E) m() {}
    66  //	var p *T
    67  //
    68  // the following relations exist:
    69  //
    70  //	Selector    Kind          Recv    Obj    Type       Index     Indirect
    71  //
    72  //	p.x         FieldVal      T       x      int        {0}       true
    73  //	p.m         MethodVal     *T      m      func()     {1, 0}    true
    74  //	T.m         MethodExpr    T       m      func(T)    {1, 0}    false
    75  type Selection struct {
    76  	kind     int8   // SelectionKind
    77  	indirect bool   // set if there was any pointer indirection on the path
    78  	recv     Type   // type of x
    79  	obj      Object // object denoted by x.f
    80  	index    []int  // path from x to x.f
    81  
    82  	// TODO(adonovan): opt: <3% of Selections have >1 index.
    83  	// Replace the slice by 'index0 [1]int' plus an optional *[]int
    84  	// for the few longer ones.
    85  }
    86  
    87  // Kind returns the selection kind.
    88  func (s *Selection) Kind() SelectionKind { return SelectionKind(s.kind) }
    89  
    90  // Recv returns the type of x in x.f.
    91  func (s *Selection) Recv() Type { return s.recv }
    92  
    93  // Obj returns the object denoted by x.f; a *Var for
    94  // a field selection, and a *Func in all other cases.
    95  func (s *Selection) Obj() Object { return s.obj }
    96  
    97  // Type returns the type of x.f, which may be different from the type of f.
    98  // See Selection for more information.
    99  func (s *Selection) Type() Type {
   100  	switch s.Kind() {
   101  	case MethodVal:
   102  		// TODO(mark) Align this with call.go if possible.
   103  		// The type of x.f is a method with its receiver type set
   104  		// to the type of x.
   105  		sig := *s.obj.(*Func).typ.(*Signature)
   106  		recv := *sig.recv
   107  		recv.typ = s.recv
   108  		sig.recv = &recv
   109  		return &sig
   110  
   111  	case MethodExpr:
   112  		// The type of x.f is a function (without receiver)
   113  		// and an additional first argument with the same type as x.
   114  		// TODO(gri) Similar code is already in call.go - factor!
   115  		// TODO(gri) Compute this eagerly to avoid allocations.
   116  		sig := *s.obj.(*Func).typ.(*Signature)
   117  		arg0 := *sig.recv
   118  		sig.recvold = sig.recv // stash receiver (for consistency with call.go)
   119  		sig.recv = nil
   120  		arg0.typ = s.recv
   121  		var params []*Var
   122  		if sig.params != nil {
   123  			params = sig.params.vars
   124  		}
   125  		sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
   126  		return &sig
   127  	}
   128  
   129  	// In all other cases, the type of x.f is the type of f.
   130  	return s.obj.Type()
   131  }
   132  
   133  // Index describes the path from x to f in x.f.
   134  // The last index entry is the field or method index of the type declaring f;
   135  // either:
   136  //
   137  //  1. the list of declared methods of a named type; or
   138  //  2. the list of methods of an interface type; or
   139  //  3. the list of fields of a struct type.
   140  //
   141  // The earlier index entries are the indices of the embedded fields implicitly
   142  // traversed to get from (the type of) x to f, starting at embedding depth 0.
   143  func (s *Selection) Index() []int { return s.index }
   144  
   145  // Indirect reports whether any pointer indirection was required to get from
   146  // x to f in x.f.
   147  //
   148  // Beware: Indirect spuriously returns true (Go issue #8353) for a
   149  // MethodVal selection in which the receiver argument and parameter
   150  // both have type *T so there is no indirection.
   151  // Unfortunately, a fix is too risky.
   152  func (s *Selection) Indirect() bool { return s.indirect }
   153  
   154  func (s *Selection) String() string { return SelectionString(s, nil) }
   155  
   156  // SelectionString returns the string form of s.
   157  // The Qualifier controls the printing of
   158  // package-level objects, and may be nil.
   159  //
   160  // Examples:
   161  //
   162  //	"field (T) f int"
   163  //	"method (T) f(X) Y"
   164  //	"method expr (T) f(X) Y"
   165  func SelectionString(s *Selection, qf Qualifier) string {
   166  	var k string
   167  	switch s.Kind() {
   168  	case FieldVal:
   169  		k = "field "
   170  	case MethodVal:
   171  		k = "method "
   172  	case MethodExpr:
   173  		k = "method expr "
   174  	default:
   175  		panic("unreachable")
   176  	}
   177  	var buf bytes.Buffer
   178  	buf.WriteString(k)
   179  	buf.WriteByte('(')
   180  	WriteType(&buf, s.Recv(), qf)
   181  	fmt.Fprintf(&buf, ") %s", s.obj.Name())
   182  	if T := s.Type(); s.Kind() == FieldVal {
   183  		buf.WriteByte(' ')
   184  		WriteType(&buf, T, qf)
   185  	} else {
   186  		WriteSignature(&buf, T.(*Signature), qf)
   187  	}
   188  	return buf.String()
   189  }
   190  

View as plain text