1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// This file implements commonly used type predicates.
6
7package types
8
9func isNamed(typ Type) bool {
10	if _, ok := typ.(*Basic); ok {
11		return ok
12	}
13	_, ok := typ.(*NamedType)
14	return ok
15}
16
17func isBoolean(typ Type) bool {
18	t, ok := underlying(typ).(*Basic)
19	return ok && t.Info&IsBoolean != 0
20}
21
22func isInteger(typ Type) bool {
23	t, ok := underlying(typ).(*Basic)
24	return ok && t.Info&IsInteger != 0
25}
26
27func isUnsigned(typ Type) bool {
28	t, ok := underlying(typ).(*Basic)
29	return ok && t.Info&IsUnsigned != 0
30}
31
32func isFloat(typ Type) bool {
33	t, ok := underlying(typ).(*Basic)
34	return ok && t.Info&IsFloat != 0
35}
36
37func isComplex(typ Type) bool {
38	t, ok := underlying(typ).(*Basic)
39	return ok && t.Info&IsComplex != 0
40}
41
42func isNumeric(typ Type) bool {
43	t, ok := underlying(typ).(*Basic)
44	return ok && t.Info&IsNumeric != 0
45}
46
47func isString(typ Type) bool {
48	t, ok := underlying(typ).(*Basic)
49	return ok && t.Info&IsString != 0
50}
51
52func isUntyped(typ Type) bool {
53	t, ok := underlying(typ).(*Basic)
54	return ok && t.Info&IsUntyped != 0
55}
56
57func isOrdered(typ Type) bool {
58	t, ok := underlying(typ).(*Basic)
59	return ok && t.Info&IsOrdered != 0
60}
61
62func isConstType(typ Type) bool {
63	t, ok := underlying(typ).(*Basic)
64	return ok && t.Info&IsConstType != 0
65}
66
67func isComparable(typ Type) bool {
68	switch t := underlying(typ).(type) {
69	case *Basic:
70		return t.Kind != Invalid && t.Kind != UntypedNil
71	case *Pointer, *Interface, *Chan:
72		// assumes types are equal for pointers and channels
73		return true
74	case *Struct:
75		for _, f := range t.Fields {
76			if !isComparable(f.Type) {
77				return false
78			}
79		}
80		return true
81	case *Array:
82		return isComparable(t.Elt)
83	}
84	return false
85}
86
87func hasNil(typ Type) bool {
88	switch underlying(typ).(type) {
89	case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
90		return true
91	}
92	return false
93}
94
95// IsIdentical returns true if x and y are identical.
96func IsIdentical(x, y Type) bool {
97	if x == y {
98		return true
99	}
100
101	switch x := x.(type) {
102	case *Basic:
103		// Basic types are singletons except for the rune and byte
104		// aliases, thus we cannot solely rely on the x == y check
105		// above.
106		if y, ok := y.(*Basic); ok {
107			return x.Kind == y.Kind
108		}
109
110	case *Array:
111		// Two array types are identical if they have identical element types
112		// and the same array length.
113		if y, ok := y.(*Array); ok {
114			return x.Len == y.Len && IsIdentical(x.Elt, y.Elt)
115		}
116
117	case *Slice:
118		// Two slice types are identical if they have identical element types.
119		if y, ok := y.(*Slice); ok {
120			return IsIdentical(x.Elt, y.Elt)
121		}
122
123	case *Struct:
124		// Two struct types are identical if they have the same sequence of fields,
125		// and if corresponding fields have the same names, and identical types,
126		// and identical tags. Two anonymous fields are considered to have the same
127		// name. Lower-case field names from different packages are always different.
128		if y, ok := y.(*Struct); ok {
129			if len(x.Fields) == len(y.Fields) {
130				for i, f := range x.Fields {
131					g := y.Fields[i]
132					if !f.QualifiedName.IsSame(g.QualifiedName) ||
133						!IsIdentical(f.Type, g.Type) ||
134						f.Tag != g.Tag ||
135						f.IsAnonymous != g.IsAnonymous {
136						return false
137					}
138				}
139				return true
140			}
141		}
142
143	case *Pointer:
144		// Two pointer types are identical if they have identical base types.
145		if y, ok := y.(*Pointer); ok {
146			return IsIdentical(x.Base, y.Base)
147		}
148
149	case *Signature:
150		// Two function types are identical if they have the same number of parameters
151		// and result values, corresponding parameter and result types are identical,
152		// and either both functions are variadic or neither is. Parameter and result
153		// names are not required to match.
154		if y, ok := y.(*Signature); ok {
155			return identicalTypes(x.Params, y.Params) &&
156				identicalTypes(x.Results, y.Results) &&
157				x.IsVariadic == y.IsVariadic
158		}
159
160	case *Interface:
161		// Two interface types are identical if they have the same set of methods with
162		// the same names and identical function types. Lower-case method names from
163		// different packages are always different. The order of the methods is irrelevant.
164		if y, ok := y.(*Interface); ok {
165			return identicalMethods(x.Methods, y.Methods) // methods are sorted
166		}
167
168	case *Map:
169		// Two map types are identical if they have identical key and value types.
170		if y, ok := y.(*Map); ok {
171			return IsIdentical(x.Key, y.Key) && IsIdentical(x.Elt, y.Elt)
172		}
173
174	case *Chan:
175		// Two channel types are identical if they have identical value types
176		// and the same direction.
177		if y, ok := y.(*Chan); ok {
178			return x.Dir == y.Dir && IsIdentical(x.Elt, y.Elt)
179		}
180
181	case *NamedType:
182		// Two named types are identical if their type names originate
183		// in the same type declaration.
184		if y, ok := y.(*NamedType); ok {
185			return x.Obj == y.Obj
186		}
187	}
188
189	return false
190}
191
192// identicalTypes returns true if both lists a and b have the
193// same length and corresponding objects have identical types.
194func identicalTypes(a, b []*Var) bool {
195	if len(a) != len(b) {
196		return false
197	}
198	for i, x := range a {
199		y := b[i]
200		if !IsIdentical(x.Type, y.Type) {
201			return false
202		}
203	}
204	return true
205}
206
207// identicalMethods returns true if both lists a and b have the
208// same length and corresponding methods have identical types.
209// TODO(gri) make this more efficient
210func identicalMethods(a, b []*Method) bool {
211	if len(a) != len(b) {
212		return false
213	}
214	m := make(map[QualifiedName]*Method)
215	for _, x := range a {
216		assert(m[x.QualifiedName] == nil) // method list must not have duplicate entries
217		m[x.QualifiedName] = x
218	}
219	for _, y := range b {
220		if x := m[y.QualifiedName]; x == nil || !IsIdentical(x.Type, y.Type) {
221			return false
222		}
223	}
224	return true
225}
226
227// underlying returns the underlying type of typ.
228func underlying(typ Type) Type {
229	// Basic types are representing themselves directly even though they are named.
230	if typ, ok := typ.(*NamedType); ok {
231		return typ.Underlying // underlying types are never NamedTypes
232	}
233	return typ
234}
235
236// deref returns a pointer's base type; otherwise it returns typ.
237func deref(typ Type) Type {
238	if typ, ok := underlying(typ).(*Pointer); ok {
239		return typ.Base
240	}
241	return typ
242}
243
244// defaultType returns the default "typed" type for an "untyped" type;
245// it returns the incoming type for all other types. If there is no
246// corresponding untyped type, the result is Typ[Invalid].
247//
248func defaultType(typ Type) Type {
249	if t, ok := typ.(*Basic); ok {
250		k := Invalid
251		switch t.Kind {
252		// case UntypedNil:
253		//      There is no default type for nil. For a good error message,
254		//      catch this case before calling this function.
255		case UntypedBool:
256			k = Bool
257		case UntypedInt:
258			k = Int
259		case UntypedRune:
260			k = Rune
261		case UntypedFloat:
262			k = Float64
263		case UntypedComplex:
264			k = Complex128
265		case UntypedString:
266			k = String
267		}
268		typ = Typ[k]
269	}
270	return typ
271}
272
273// missingMethod returns (nil, false) if typ implements T, otherwise
274// it returns the first missing method required by T and whether it
275// is missing or simply has the wrong type.
276//
277func missingMethod(typ Type, T *Interface) (method *Method, wrongType bool) {
278	// TODO(gri): this needs to correctly compare method names (taking package into account)
279	// TODO(gri): distinguish pointer and non-pointer receivers
280	// an interface type implements T if it has no methods with conflicting signatures
281	// Note: This is stronger than the current spec. Should the spec require this?
282	if ityp, _ := underlying(typ).(*Interface); ityp != nil {
283		for _, m := range T.Methods {
284			mode, sig := lookupField(ityp, m.QualifiedName) // TODO(gri) no need to go via lookupField
285			if mode != invalid && !IsIdentical(sig, m.Type) {
286				return m, true
287			}
288		}
289		return
290	}
291
292	// a concrete type implements T if it implements all methods of T.
293	for _, m := range T.Methods {
294		mode, sig := lookupField(typ, m.QualifiedName)
295		if mode == invalid {
296			return m, false
297		}
298		if !IsIdentical(sig, m.Type) {
299			return m, true
300		}
301	}
302	return
303}
304