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