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