selection.go raw

   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     SelectionKind
  77  	recv     Type   // type of x
  78  	obj      Object // object denoted by x.f
  79  	index    []int  // path from x to x.f
  80  	indirect bool   // set if there was any pointer indirection on the path
  81  }
  82  
  83  // Kind returns the selection kind.
  84  func (s *Selection) Kind() SelectionKind { return s.kind }
  85  
  86  // Recv returns the type of x in x.f.
  87  func (s *Selection) Recv() Type { return s.recv }
  88  
  89  // Obj returns the object denoted by x.f; a *Var for
  90  // a field selection, and a *Func in all other cases.
  91  func (s *Selection) Obj() Object { return s.obj }
  92  
  93  // Type returns the type of x.f, which may be different from the type of f.
  94  // See Selection for more information.
  95  func (s *Selection) Type() Type {
  96  	switch s.kind {
  97  	case MethodVal:
  98  		// The type of x.f is a method with its receiver type set
  99  		// to the type of x.
 100  		sig := *s.obj.(*Func).typ.(*Signature)
 101  		recv := *sig.recv
 102  		recv.typ = s.recv
 103  		sig.recv = &recv
 104  		return &sig
 105  
 106  	case MethodExpr:
 107  		// The type of x.f is a function (without receiver)
 108  		// and an additional first argument with the same type as x.
 109  		// TODO(gri) Similar code is already in call.go - factor!
 110  		// TODO(gri) Compute this eagerly to avoid allocations.
 111  		sig := *s.obj.(*Func).typ.(*Signature)
 112  		arg0 := *sig.recv
 113  		sig.recv = nil
 114  		arg0.typ = s.recv
 115  		var params []*Var
 116  		if sig.params != nil {
 117  			params = sig.params.vars
 118  		}
 119  		sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
 120  		return &sig
 121  	}
 122  
 123  	// In all other cases, the type of x.f is the type of x.
 124  	return s.obj.Type()
 125  }
 126  
 127  // Index describes the path from x to f in x.f.
 128  // The last index entry is the field or method index of the type declaring f;
 129  // either:
 130  //
 131  //  1. the list of declared methods of a named type; or
 132  //  2. the list of methods of an interface type; or
 133  //  3. the list of fields of a struct type.
 134  //
 135  // The earlier index entries are the indices of the embedded fields implicitly
 136  // traversed to get from (the type of) x to f, starting at embedding depth 0.
 137  func (s *Selection) Index() []int { return s.index }
 138  
 139  // Indirect reports whether any pointer indirection was required to get from
 140  // x to f in x.f.
 141  //
 142  // Beware: Indirect spuriously returns true (Go issue #8353) for a
 143  // MethodVal selection in which the receiver argument and parameter
 144  // both have type *T so there is no indirection.
 145  // Unfortunately, a fix is too risky.
 146  func (s *Selection) Indirect() bool { return s.indirect }
 147  
 148  func (s *Selection) String() string { return SelectionString(s, nil) }
 149  
 150  // SelectionString returns the string form of s.
 151  // The Qualifier controls the printing of
 152  // package-level objects, and may be nil.
 153  //
 154  // Examples:
 155  //
 156  //	"field (T) f int"
 157  //	"method (T) f(X) Y"
 158  //	"method expr (T) f(X) Y"
 159  func SelectionString(s *Selection, qf Qualifier) string {
 160  	var k string
 161  	switch s.kind {
 162  	case FieldVal:
 163  		k = "field "
 164  	case MethodVal:
 165  		k = "method "
 166  	case MethodExpr:
 167  		k = "method expr "
 168  	default:
 169  		panic("unreachable")
 170  	}
 171  	var buf bytes.Buffer
 172  	buf.WriteString(k)
 173  	buf.WriteByte('(')
 174  	WriteType(&buf, s.Recv(), qf)
 175  	fmt.Fprintf(&buf, ") %s", s.obj.Name())
 176  	if T := s.Type(); s.kind == FieldVal {
 177  		buf.WriteByte(' ')
 178  		WriteType(&buf, T, qf)
 179  	} else {
 180  		WriteSignature(&buf, T.(*Signature), qf)
 181  	}
 182  	return buf.String()
 183  }
 184