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 10package types 11 12import ( 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. 52type SelectionKind int 53 54const ( 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 75type 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. 84func (s *Selection) Kind() SelectionKind { return s.kind } 85 86// Recv returns the type of x in x.f. 87func (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. 91func (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. 95func (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. 137func (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. 146func (s *Selection) Indirect() bool { return s.indirect } 147 148func (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" 159func 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