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