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