Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // The reflect package implements run-time reflection, allowing a program to | 5 // The reflect package implements run-time reflection, allowing a program to |
6 // manipulate objects with arbitrary types. The typical use is to take a | 6 // manipulate objects with arbitrary types. The typical use is to take a |
7 // value with static type interface{} and extract its dynamic type | 7 // value with static type interface{} and extract its dynamic type |
8 // information by calling Typeof, which returns an object with interface | 8 // information by calling Typeof, which returns a Type. |
9 // type Type. That contains a pointer to a struct of type *StructType, | |
10 // *IntType, etc. representing the details of the underlying type. A type | |
11 // switch or type assertion can reveal which. | |
12 // | 9 // |
13 // A call to NewValue creates a Value representing the run-time data; it | 10 // A call to NewValue returns a Value representing the run-time data. |
14 // contains a *StructValue, *IntValue, etc. MakeZero takes a Type and | 11 // MakeZero takes a Type and returns a Value representing a zero value |
15 // returns a Value representing a zero value for that type. | 12 // for that type. |
16 package reflect | 13 package reflect |
17 | 14 |
18 import ( | 15 import ( |
19 "runtime" | 16 "runtime" |
20 "strconv" | 17 "strconv" |
21 "sync" | 18 "sync" |
22 "unsafe" | 19 "unsafe" |
23 ) | 20 ) |
24 | 21 |
25 /* | 22 /* |
23 We want to be able to call methods on Type and to compare types for equality. | |
r
2011/04/02 18:45:33
i think this comment can go. at least it needs rep
| |
24 Thus Type must be either an opaque type or an interface. | |
25 If we make it an interface then existing code changes less. | |
26 If we make Type an opaque type then that could allow overwriting | |
27 type data using copying. It also means saying *Type everywhere | |
28 but plain Value (not *Value), which is a bit strange. Let's use | |
29 the interface for better protection and to lose the *. | |
30 | |
31 | |
32 */ | |
33 | |
34 // Type is the representation of a Go type. | |
r
2011/04/02 18:45:33
might be good to have helper methods or functions
| |
35 // | |
36 // Not all methods apply to all kinds of types. Restrictions, | |
37 // if any, are noted in the documentation for each method. | |
38 // Use the Kind method to find out the kind of type before | |
39 // calling kind-specific methods. Calling a method | |
40 // inappropriate to the kind of type causes a run time panic. | |
r
2011/04/02 18:45:33
s/run time/run-time/ (adjective)
| |
41 type Type interface { | |
42 // Methods applicable to all types. | |
43 | |
44 // Align returns the alignment of a value of this type | |
45 // when allocated in memory. | |
r
2011/04/02 18:45:33
what units?
| |
46 Align() int | |
47 | |
48 // FieldAlign returns the alignment of a value of this type | |
49 // when used as a field in a struct. | |
r
2011/04/02 18:45:33
what units?
| |
50 FieldAlign() int | |
51 | |
52 // Method returns the i'th method in the type's method set. | |
r
2011/04/02 18:45:33
what happens if i is out of range?
obviously, it p
| |
53 // | |
54 // For a non-interface type T or *T, the returned Method's Type and Func | |
55 // fields describe a function whose first argument is the receiver. | |
56 // | |
57 // For an interface type, the returned Method's Type field gives the | |
58 // method signature, without a receiver, and the Func field is nil. | |
59 Method(int) Method | |
60 | |
61 // NumMethods returns the number of methods in the type's method set. | |
62 NumMethod() int | |
63 | |
64 // Name returns the type's name within its package. | |
r
2011/04/02 18:45:33
really? i thought it returned pkg.NameOfType
| |
65 // It returns an empty string for unnamed types. | |
66 Name() string | |
67 | |
68 // PkgPath returns the type's package path. | |
69 // The package path is a full package import path like "container/vector ". | |
70 // PkgPath returns an empty string for unnamed types. | |
71 PkgPath() string | |
72 | |
73 // Size returns the number of bytes needed to store | |
74 // a value of the given type; it is analogous to unsafe.Sizeof. | |
75 Size() uintptr | |
76 | |
77 // String returns a string representation of the type. | |
78 // The string representation may use shortened package names | |
79 // (e.g., vector instead of "container/vector") and is not | |
80 // guaranteed to be unique among types. To test for equality, | |
81 // compare the Types directly. | |
82 String() string | |
83 | |
84 // Kind returns the specific kind of this type. | |
85 Kind() Kind | |
86 | |
87 // Methods applicable only to some types, depending on Kind. | |
88 // The methods allowed for each kind are: | |
89 // | |
90 // Int*, Uint*, Float*, Complex*: Bits | |
91 // Array: Elem, Len | |
92 // Chan: ChanDir, Elem | |
93 // Func: In, NumIn, Out, NumOut, DotDotDot. | |
94 // Map: Key, Elem | |
95 // Ptr: Elem | |
96 // Slice: Elem | |
97 // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumFi eld | |
98 | |
99 // Bits returns the size of the type in bits. | |
100 // It panics if the type's Kind is not one of the | |
101 // sized or unsized Int, Uint, Float, or Complex knids. | |
102 Bits() int | |
103 | |
104 // ChanDir returns a channel type's direction. | |
105 // It panics if the type's Kind is not Chan. | |
106 ChanDir() ChanDir | |
107 | |
108 // DotDotDot returns true if a function type's final input parameter | |
109 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the paramet er's | |
110 // underlying static type []T. | |
111 // | |
112 // For concreteness, if t represents func(x int, y ... float), then | |
113 // | |
114 // t.NumIn() == 2 | |
115 // t.In(0) is the reflect.Type for "int" | |
116 // t.In(1) is the reflect.Type for "[]float" | |
117 // t.DotDotDot() == true | |
118 // | |
119 // DotDotDot panics if the type's Kind is not Func. | |
120 DotDotDot() bool | |
r
2011/04/02 18:45:33
wrong name for a boolean method. HasDotDotDot is
| |
121 | |
122 // Elem returns a type's element type. | |
niemeyer
2011/04/04 13:52:35
s/element type/element Type/ ?
rsc
2011/04/05 16:29:45
I intentionally left type lower case in most place
| |
123 // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice. | |
124 Elem() Type | |
125 | |
126 // Field returns a struct type's i'th field. | |
r
2011/04/02 18:45:33
what if i is out of range?
| |
127 // It panics if the type's Kind is not Struct. | |
128 Field(i int) StructField | |
129 | |
130 // FieldByIndex returns the nested field corresponding | |
131 // to the index sequence. It is equivalent to calling Field | |
132 // successively for each index i. | |
133 // It panics if the type's Kind is not Struct. | |
134 FieldByIndex(index []int) StructField | |
135 | |
136 // FieldByName returns the struct field with the given name | |
137 // and a boolean indicating if the field was found. | |
138 FieldByName(name string) (StructField, bool) | |
139 | |
140 // FieldByNameFunc returns the first struct field with a name | |
141 // that satisfies the match function and a boolean indicating if | |
142 // the field was found. | |
143 FieldByNameFunc(match func(string) bool) (StructField, bool) | |
144 | |
145 // In returns the type of a function type's i'th input parameter. | |
146 // It panics if the type's Kind is not Func. | |
r
2011/04/02 18:45:33
here and for Out: what if i is out of range?
| |
147 In(i int) Type | |
148 | |
149 // Key returns a map type's key type. | |
150 // It panics if the type's Kind is not Map. | |
151 Key() Type | |
niemeyer
2011/04/04 13:52:35
Should this be called MapKey, or MapKeys be rename
rsc
2011/04/05 16:29:45
I don't think so. SliceType still uses Elem() to
| |
152 | |
153 // Len returns an array type's length. | |
154 // It panics if the type's Kind is not Array. | |
155 Len() int | |
156 | |
157 // NumField returns a struct type's field count. | |
158 // It panics if the type's Kind is not Struct. | |
159 NumField() int | |
160 | |
161 // NumIn returns a function type's input parameter count. | |
162 // It panics if the type's Kind is not Func. | |
163 NumIn() int | |
164 | |
165 // NumOut returns a function type's output parameter count. | |
166 // It panics if the type's Kind is not Func. | |
167 NumOut() int | |
168 | |
169 // Out returns the type of a function type's i'th output parameter. | |
170 // It panics if the type's Kind is not Func. | |
171 Out(i int) Type | |
172 | |
173 uncommon() *uncommonType | |
174 } | |
175 | |
176 // A Kind represents the specific kind of type that a Type represents. | |
177 // The zero Kind is not a valid kind. | |
178 type Kind uint8 | |
179 | |
180 const ( | |
181 Invalid Kind = iota | |
182 Bool | |
183 Int | |
184 Int8 | |
185 Int16 | |
186 Int32 | |
187 Int64 | |
188 Uint | |
189 Uint8 | |
190 Uint16 | |
191 Uint32 | |
192 Uint64 | |
193 Uintptr | |
194 Float32 | |
195 Float64 | |
196 Complex64 | |
197 Complex128 | |
198 Array | |
199 Chan | |
200 Func | |
201 Interface | |
202 Map | |
203 Ptr | |
204 Slice | |
205 String | |
206 Struct | |
207 UnsafePointer | |
208 ) | |
209 | |
210 /* | |
26 * Copy of data structures from ../runtime/type.go. | 211 * Copy of data structures from ../runtime/type.go. |
27 * For comments, see the ones in that file. | 212 * For comments, see the ones in that file. |
28 * | 213 * |
29 * These data structures are known to the compiler and the runtime. | 214 * These data structures are known to the compiler and the runtime. |
30 * | 215 * |
31 * Putting these types in runtime instead of reflect means that | 216 * Putting these types in runtime instead of reflect means that |
32 * reflect doesn't need to be autolinked into every binary, which | 217 * reflect doesn't need to be autolinked into every binary, which |
33 * simplifies bootstrapping and package dependencies. | 218 * simplifies bootstrapping and package dependencies. |
34 * Unfortunately, it also means that reflect needs its own | 219 * Unfortunately, it also means that reflect needs its own |
35 * copy in order to access the private fields. | 220 * copy in order to access the private fields. |
(...skipping 24 matching lines...) Expand all Loading... | |
60 ifn unsafe.Pointer | 245 ifn unsafe.Pointer |
61 tfn unsafe.Pointer | 246 tfn unsafe.Pointer |
62 } | 247 } |
63 | 248 |
64 type uncommonType struct { | 249 type uncommonType struct { |
65 name *string | 250 name *string |
66 pkgPath *string | 251 pkgPath *string |
67 methods []method | 252 methods []method |
68 } | 253 } |
69 | 254 |
70 // BoolType represents a boolean type. | |
71 type BoolType struct { | |
72 commonType "bool" | |
73 } | |
74 | |
75 // FloatType represents a float type. | |
76 type FloatType struct { | |
77 commonType "float" | |
78 } | |
79 | |
80 // ComplexType represents a complex type. | |
81 type ComplexType struct { | |
82 commonType "complex" | |
83 } | |
84 | |
85 // IntType represents a signed integer type. | |
86 type IntType struct { | |
87 commonType "int" | |
88 } | |
89 | |
90 // UintType represents a uint type. | |
91 type UintType struct { | |
92 commonType "uint" | |
93 } | |
94 | |
95 // StringType represents a string type. | |
96 type StringType struct { | |
97 commonType "string" | |
98 } | |
99 | |
100 // UnsafePointerType represents an unsafe.Pointer type. | |
101 type UnsafePointerType struct { | |
102 commonType "unsafe.Pointer" | |
103 } | |
104 | |
105 // ArrayType represents a fixed array type. | |
106 type ArrayType struct { | |
107 commonType "array" | |
108 elem *runtime.Type | |
109 len uintptr | |
110 } | |
111 | |
112 // ChanDir represents a channel type's direction. | 255 // ChanDir represents a channel type's direction. |
113 type ChanDir int | 256 type ChanDir int |
114 | 257 |
115 const ( | 258 const ( |
116 RecvDir ChanDir = 1 << iota | 259 RecvDir ChanDir = 1 << iota |
117 SendDir | 260 SendDir |
118 BothDir = RecvDir | SendDir | 261 BothDir = RecvDir | SendDir |
119 ) | 262 ) |
120 | 263 |
121 // ChanType represents a channel type. | 264 |
122 type ChanType struct { | 265 // arrayType represents a fixed array type. |
266 type arrayType struct { | |
267 » commonType "array" | |
268 » elem *runtime.Type | |
269 » len uintptr | |
270 } | |
271 | |
272 // chanType represents a channel type. | |
273 type chanType struct { | |
123 commonType "chan" | 274 commonType "chan" |
124 elem *runtime.Type | 275 elem *runtime.Type |
125 dir uintptr | 276 dir uintptr |
126 } | 277 } |
127 | 278 |
128 // FuncType represents a function type. | 279 // funcType represents a function type. |
129 type FuncType struct { | 280 type funcType struct { |
130 commonType "func" | 281 commonType "func" |
131 dotdotdot bool | 282 dotdotdot bool |
132 in []*runtime.Type | 283 in []*runtime.Type |
133 out []*runtime.Type | 284 out []*runtime.Type |
134 } | 285 } |
135 | 286 |
136 // Method on interface type | 287 // imethod represents a method on an interface type |
137 type imethod struct { | 288 type imethod struct { |
138 name *string | 289 name *string |
139 pkgPath *string | 290 pkgPath *string |
140 typ *runtime.Type | 291 typ *runtime.Type |
141 } | 292 } |
142 | 293 |
143 // InterfaceType represents an interface type. | 294 // interfaceType represents an interface type. |
144 type InterfaceType struct { | 295 type interfaceType struct { |
145 commonType "interface" | 296 commonType "interface" |
146 methods []imethod | 297 methods []imethod |
147 } | 298 } |
148 | 299 |
149 // MapType represents a map type. | 300 // mapType represents a map type. |
150 type MapType struct { | 301 type mapType struct { |
151 commonType "map" | 302 commonType "map" |
152 key *runtime.Type | 303 key *runtime.Type |
153 elem *runtime.Type | 304 elem *runtime.Type |
154 } | 305 } |
155 | 306 |
156 // PtrType represents a pointer type. | 307 // ptrType represents a pointer type. |
157 type PtrType struct { | 308 type ptrType struct { |
158 commonType "ptr" | 309 commonType "ptr" |
159 elem *runtime.Type | 310 elem *runtime.Type |
160 } | 311 } |
161 | 312 |
162 // SliceType represents a slice type. | 313 // sliceType represents a slice type. |
163 type SliceType struct { | 314 type sliceType struct { |
164 commonType "slice" | 315 commonType "slice" |
165 elem *runtime.Type | 316 elem *runtime.Type |
166 } | 317 } |
167 | 318 |
168 // arrayOrSliceType is an unexported method that guarantees only | |
169 // arrays and slices implement ArrayOrSliceType. | |
170 func (*SliceType) arrayOrSliceType() {} | |
171 | |
172 // Struct field | 319 // Struct field |
173 type structField struct { | 320 type structField struct { |
174 name *string | 321 name *string |
175 pkgPath *string | 322 pkgPath *string |
176 typ *runtime.Type | 323 typ *runtime.Type |
177 tag *string | 324 tag *string |
178 offset uintptr | 325 offset uintptr |
179 } | 326 } |
180 | 327 |
181 // StructType represents a struct type. | 328 // structType represents a struct type. |
182 type StructType struct { | 329 type structType struct { |
183 commonType "struct" | 330 commonType "struct" |
184 fields []structField | 331 fields []structField |
185 } | 332 } |
186 | 333 |
187 | 334 |
188 /* | 335 /* |
189 * The compiler knows the exact layout of all the data structures above. | 336 * The compiler knows the exact layout of all the data structures above. |
190 * The compiler does not know about the data structures and methods below. | 337 * The compiler does not know about the data structures and methods below. |
191 */ | 338 */ |
192 | 339 |
193 // Method represents a single method. | 340 // Method represents a single method. |
194 type Method struct { | 341 type Method struct { |
195 PkgPath string // empty for uppercase Name | 342 PkgPath string // empty for uppercase Name |
196 Name string | 343 Name string |
197 » Type *FuncType | 344 » Type Type |
198 » Func *FuncValue | 345 » Func Value |
199 } | 346 } |
200 | 347 |
201 // Type is the runtime representation of a Go type. | |
202 // Every type implements the methods listed here. | |
203 // Some types implement additional interfaces; | |
204 // use a type switch to find out what kind of type a Type is. | |
205 // Each type in a program has a unique Type, so == on Types | |
206 // corresponds to Go's type equality. | |
207 type Type interface { | |
208 // PkgPath returns the type's package path. | |
209 // The package path is a full package import path like "container/vector ". | |
210 // PkgPath returns an empty string for unnamed types. | |
211 PkgPath() string | |
212 | |
213 // Name returns the type's name within its package. | |
214 // Name returns an empty string for unnamed types. | |
215 Name() string | |
216 | |
217 // String returns a string representation of the type. | |
218 // The string representation may use shortened package names | |
219 // (e.g., vector instead of "container/vector") and is not | |
220 // guaranteed to be unique among types. To test for equality, | |
221 // compare the Types directly. | |
222 String() string | |
223 | |
224 // Size returns the number of bytes needed to store | |
225 // a value of the given type; it is analogous to unsafe.Sizeof. | |
226 Size() uintptr | |
227 | |
228 // Bits returns the size of the type in bits. | |
229 // It is intended for use with numeric types and may overflow | |
230 // when used for composite types. | |
231 Bits() int | |
232 | |
233 // Align returns the alignment of a value of this type | |
234 // when allocated in memory. | |
235 Align() int | |
236 | |
237 // FieldAlign returns the alignment of a value of this type | |
238 // when used as a field in a struct. | |
239 FieldAlign() int | |
240 | |
241 // Kind returns the specific kind of this type. | |
242 Kind() Kind | |
243 | |
244 // Method returns the i'th method in the type's method set. | |
245 // | |
246 // For a non-interface type T or *T, the returned Method's Type and Func | |
247 // fields describe a function whose first argument is the receiver. | |
248 // | |
249 // For an interface type, the returned Method's Type field gives the | |
250 // method signature, without a receiver, and the Func field is nil. | |
251 Method(int) Method | |
252 | |
253 // NumMethods returns the number of methods in the type's method set. | |
254 NumMethod() int | |
255 | |
256 common() *commonType | |
257 uncommon() *uncommonType | |
258 } | |
259 | |
260 // A Kind represents the specific kind of type that a Type represents. | |
261 // For numeric types, the Kind gives more information than the Type's | |
262 // dynamic type. For example, the Type of a float32 is FloatType, but | |
263 // the Kind is Float32. | |
264 // | |
265 // The zero Kind is not a valid kind. | |
266 type Kind uint8 | |
267 | |
268 const ( | |
269 Bool Kind = 1 + iota | |
270 Int | |
271 Int8 | |
272 Int16 | |
273 Int32 | |
274 Int64 | |
275 Uint | |
276 Uint8 | |
277 Uint16 | |
278 Uint32 | |
279 Uint64 | |
280 Uintptr | |
281 Float32 | |
282 Float64 | |
283 Complex64 | |
284 Complex128 | |
285 Array | |
286 Chan | |
287 Func | |
288 Interface | |
289 Map | |
290 Ptr | |
291 Slice | |
292 String | |
293 Struct | |
294 UnsafePointer | |
295 ) | |
296 | |
297 // High bit says whether type has | 348 // High bit says whether type has |
298 // embedded pointers,to help garbage collector. | 349 // embedded pointers,to help garbage collector. |
299 const kindMask = 0x7f | 350 const kindMask = 0x7f |
300 | 351 |
301 func (k Kind) String() string { | 352 func (k Kind) String() string { |
302 if int(k) < len(kindNames) { | 353 if int(k) < len(kindNames) { |
303 return kindNames[k] | 354 return kindNames[k] |
304 } | 355 } |
305 return "kind" + strconv.Itoa(int(k)) | 356 return "kind" + strconv.Itoa(int(k)) |
306 } | 357 } |
307 | 358 |
308 var kindNames = []string{ | 359 var kindNames = []string{ |
360 Invalid: "invalid", | |
309 Bool: "bool", | 361 Bool: "bool", |
310 Int: "int", | 362 Int: "int", |
311 Int8: "int8", | 363 Int8: "int8", |
312 Int16: "int16", | 364 Int16: "int16", |
313 Int32: "int32", | 365 Int32: "int32", |
314 Int64: "int64", | 366 Int64: "int64", |
315 Uint: "uint", | 367 Uint: "uint", |
316 Uint8: "uint8", | 368 Uint8: "uint8", |
317 Uint16: "uint16", | 369 Uint16: "uint16", |
318 Uint32: "uint32", | 370 Uint32: "uint32", |
(...skipping 26 matching lines...) Expand all Loading... | |
345 return *t.pkgPath | 397 return *t.pkgPath |
346 } | 398 } |
347 | 399 |
348 func (t *uncommonType) Name() string { | 400 func (t *uncommonType) Name() string { |
349 if t == nil || t.name == nil { | 401 if t == nil || t.name == nil { |
350 return "" | 402 return "" |
351 } | 403 } |
352 return *t.name | 404 return *t.name |
353 } | 405 } |
354 | 406 |
407 func (t *commonType) toType() Type { | |
408 if t == nil { | |
409 return nil | |
410 } | |
411 return t | |
412 } | |
413 | |
355 func (t *commonType) String() string { return *t.string } | 414 func (t *commonType) String() string { return *t.string } |
356 | 415 |
357 func (t *commonType) Size() uintptr { return t.size } | 416 func (t *commonType) Size() uintptr { return t.size } |
358 | 417 |
359 func (t *commonType) Bits() int { return int(t.size * 8) } | 418 func (t *commonType) Bits() int { |
419 » k := t.Kind() | |
420 » if k < Int || k > Complex128 { | |
421 » » panic("reflect: Bits of non-arithmetic Type") | |
422 » } | |
423 » return int(t.size) * 8 | |
424 } | |
360 | 425 |
361 func (t *commonType) Align() int { return int(t.align) } | 426 func (t *commonType) Align() int { return int(t.align) } |
362 | 427 |
363 func (t *commonType) FieldAlign() int { return int(t.fieldAlign) } | 428 func (t *commonType) FieldAlign() int { return int(t.fieldAlign) } |
364 | 429 |
365 func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) } | 430 func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) } |
366 | 431 |
367 func (t *commonType) common() *commonType { return t } | 432 func (t *commonType) common() *commonType { return t } |
368 | 433 |
369 func (t *uncommonType) Method(i int) (m Method) { | 434 func (t *uncommonType) Method(i int) (m Method) { |
370 if t == nil || i < 0 || i >= len(t.methods) { | 435 if t == nil || i < 0 || i >= len(t.methods) { |
371 return | 436 return |
372 } | 437 } |
373 p := &t.methods[i] | 438 p := &t.methods[i] |
374 if p.name != nil { | 439 if p.name != nil { |
375 m.Name = *p.name | 440 m.Name = *p.name |
376 } | 441 } |
377 if p.pkgPath != nil { | 442 if p.pkgPath != nil { |
378 m.PkgPath = *p.pkgPath | 443 m.PkgPath = *p.pkgPath |
379 } | 444 } |
380 » m.Type = toType(*p.typ).(*FuncType) | 445 » m.Type = toType(p.typ) |
381 fn := p.tfn | 446 fn := p.tfn |
382 » m.Func = &FuncValue{value: value{m.Type, addr(&fn), canSet}} | 447 » m.Func = Value{&funcValue{value: value{m.Type, addr(&fn), canSet}}} |
383 return | 448 return |
384 } | 449 } |
385 | 450 |
386 func (t *uncommonType) NumMethod() int { | 451 func (t *uncommonType) NumMethod() int { |
387 if t == nil { | 452 if t == nil { |
388 return 0 | 453 return 0 |
389 } | 454 } |
390 return len(t.methods) | 455 return len(t.methods) |
391 } | 456 } |
392 | 457 |
393 // TODO(rsc): 6g supplies these, but they are not | 458 // TODO(rsc): 6g supplies these, but they are not |
394 // as efficient as they could be: they have commonType | 459 // as efficient as they could be: they have commonType |
395 // as the receiver instead of *commonType. | 460 // as the receiver instead of *commonType. |
396 func (t *commonType) NumMethod() int { return t.uncommonType.NumMethod() } | 461 func (t *commonType) NumMethod() int { |
462 » if t.Kind() == Interface { | |
463 » » tt := (*interfaceType)(unsafe.Pointer(t)) | |
464 » » return tt.NumMethod() | |
465 » } | |
466 » return t.uncommonType.NumMethod() | |
467 } | |
397 | 468 |
398 func (t *commonType) Method(i int) (m Method) { return t.uncommonType.Method(i) } | 469 func (t *commonType) Method(i int) (m Method) { |
470 » if t.Kind() == Interface { | |
471 » » tt := (*interfaceType)(unsafe.Pointer(t)) | |
472 » » return tt.Method(i) | |
473 » } | |
474 » return t.uncommonType.Method(i) | |
475 } | |
399 | 476 |
400 func (t *commonType) PkgPath() string { return t.uncommonType.PkgPath() } | 477 func (t *commonType) PkgPath() string { |
478 » return t.uncommonType.PkgPath() | |
479 } | |
401 | 480 |
402 func (t *commonType) Name() string { return t.uncommonType.Name() } | 481 func (t *commonType) Name() string { |
482 » return t.uncommonType.Name() | |
483 } | |
403 | 484 |
404 // Len returns the number of elements in the array. | 485 func (t *commonType) ChanDir() ChanDir { |
405 func (t *ArrayType) Len() int { return int(t.len) } | 486 » if t.Kind() != Chan { |
487 » » panic("reflect: ChanDir of non-chan type") | |
488 » } | |
489 » tt := (*chanType)(unsafe.Pointer(t)) | |
490 » return ChanDir(tt.dir) | |
491 } | |
406 | 492 |
407 // Elem returns the type of the array's elements. | 493 func (t *commonType) DotDotDot() bool { |
408 func (t *ArrayType) Elem() Type { return toType(*t.elem) } | 494 » if t.Kind() != Func { |
495 » » panic("reflect: DotDotDot of non-func type") | |
496 » } | |
497 » tt := (*funcType)(unsafe.Pointer(t)) | |
498 » return tt.dotdotdot | |
499 } | |
409 | 500 |
410 // arrayOrSliceType is an unexported method that guarantees only | 501 func (t *commonType) Elem() Type { |
411 // arrays and slices implement ArrayOrSliceType. | 502 » switch t.Kind() { |
412 func (*ArrayType) arrayOrSliceType() {} | 503 » case Array: |
504 » » tt := (*arrayType)(unsafe.Pointer(t)) | |
505 » » return toType(tt.elem) | |
506 » case Chan: | |
507 » » tt := (*chanType)(unsafe.Pointer(t)) | |
508 » » return toType(tt.elem) | |
509 » case Map: | |
510 » » tt := (*mapType)(unsafe.Pointer(t)) | |
511 » » return toType(tt.elem) | |
512 » case Ptr: | |
513 » » tt := (*ptrType)(unsafe.Pointer(t)) | |
514 » » return toType(tt.elem) | |
515 » case Slice: | |
516 » » tt := (*sliceType)(unsafe.Pointer(t)) | |
517 » » return toType(tt.elem) | |
518 » } | |
519 » panic("reflect; Elem of invalid type") | |
520 } | |
413 | 521 |
414 // Dir returns the channel direction. | 522 func (t *commonType) Field(i int) StructField { |
415 func (t *ChanType) Dir() ChanDir { return ChanDir(t.dir) } | 523 » if t.Kind() != Struct { |
524 » » panic("reflect: Field of non-struct type") | |
niemeyer
2011/04/04 13:52:35
It would be helpful to have a TypeError analogous
rsc
2011/04/05 16:29:45
Sure, I will add that in a separate CL.
| |
525 » } | |
526 » tt := (*structType)(unsafe.Pointer(t)) | |
527 » return tt.Field(i) | |
528 } | |
416 | 529 |
417 // Elem returns the channel's element type. | 530 func (t *commonType) FieldByIndex(index []int) StructField { |
418 func (t *ChanType) Elem() Type { return toType(*t.elem) } | 531 » if t.Kind() != Struct { |
532 » » panic("reflect: FieldByIndex of non-struct type") | |
533 » } | |
534 » tt := (*structType)(unsafe.Pointer(t)) | |
535 » return tt.FieldByIndex(index) | |
536 } | |
537 | |
538 func (t *commonType) FieldByName(name string) (StructField, bool) { | |
539 » if t.Kind() != Struct { | |
540 » » panic("reflect: FieldByName of non-struct type") | |
541 » } | |
542 » tt := (*structType)(unsafe.Pointer(t)) | |
543 » return tt.FieldByName(name) | |
544 } | |
545 | |
546 func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool ) { | |
547 » if t.Kind() != Struct { | |
548 » » panic("reflect: FieldByNameFunc of non-struct type") | |
549 » } | |
550 » tt := (*structType)(unsafe.Pointer(t)) | |
551 » return tt.FieldByNameFunc(match) | |
552 } | |
553 | |
554 func (t *commonType) In(i int) Type { | |
555 » if t.Kind() != Func { | |
556 » » panic("reflect: In of non-func type") | |
557 » } | |
558 » tt := (*funcType)(unsafe.Pointer(t)) | |
559 » return toType(tt.in[i]) | |
560 } | |
561 | |
562 func (t *commonType) Key() Type { | |
563 » if t.Kind() != Map { | |
564 » » panic("reflect: Key of non-map type") | |
565 » } | |
566 » tt := (*mapType)(unsafe.Pointer(t)) | |
567 » return toType(tt.key) | |
568 } | |
569 | |
570 func (t *commonType) Len() int { | |
571 » if t.Kind() != Array { | |
572 » » panic("reflect: Len of non-array type") | |
573 » } | |
574 » tt := (*arrayType)(unsafe.Pointer(t)) | |
575 » return int(tt.len) | |
576 } | |
577 | |
578 func (t *commonType) NumField() int { | |
579 » if t.Kind() != Struct { | |
580 » » panic("reflect: NumField of non-struct type") | |
581 » } | |
582 » tt := (*structType)(unsafe.Pointer(t)) | |
583 » return len(tt.fields) | |
584 } | |
585 | |
586 func (t *commonType) NumIn() int { | |
587 » if t.Kind() != Func { | |
588 » » panic("reflect; NumIn of non-func type") | |
589 » } | |
590 » tt := (*funcType)(unsafe.Pointer(t)) | |
591 » return len(tt.in) | |
592 } | |
593 | |
594 func (t *commonType) NumOut() int { | |
595 » if t.Kind() != Func { | |
596 » » panic("reflect; NumOut of non-func type") | |
597 » } | |
598 » tt := (*funcType)(unsafe.Pointer(t)) | |
599 » return len(tt.out) | |
600 } | |
601 | |
602 func (t *commonType) Out(i int) Type { | |
603 » if t.Kind() != Func { | |
604 » » panic("reflect: Out of non-func type") | |
605 » } | |
606 » tt := (*funcType)(unsafe.Pointer(t)) | |
607 » return toType(tt.out[i]) | |
608 } | |
419 | 609 |
420 func (d ChanDir) String() string { | 610 func (d ChanDir) String() string { |
421 switch d { | 611 switch d { |
422 case SendDir: | 612 case SendDir: |
423 return "chan<-" | 613 return "chan<-" |
424 case RecvDir: | 614 case RecvDir: |
425 return "<-chan" | 615 return "<-chan" |
426 case BothDir: | 616 case BothDir: |
427 return "chan" | 617 return "chan" |
428 } | 618 } |
429 return "ChanDir" + strconv.Itoa(int(d)) | 619 return "ChanDir" + strconv.Itoa(int(d)) |
430 } | 620 } |
431 | 621 |
432 // In returns the type of the i'th function input parameter. | |
433 func (t *FuncType) In(i int) Type { | |
434 if i < 0 || i >= len(t.in) { | |
435 return nil | |
436 } | |
437 return toType(*t.in[i]) | |
438 } | |
439 | |
440 // DotDotDot returns true if the final function input parameter | |
441 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the | |
442 // parameter's underlying static type []T. | |
443 // | |
444 // For concreteness, if t is func(x int, y ... float), then | |
445 // | |
446 // t.NumIn() == 2 | |
447 // t.In(0) is the reflect.Type for "int" | |
448 // t.In(1) is the reflect.Type for "[]float" | |
449 // t.DotDotDot() == true | |
450 // | |
451 func (t *FuncType) DotDotDot() bool { return t.dotdotdot } | |
452 | |
453 // NumIn returns the number of input parameters. | |
454 func (t *FuncType) NumIn() int { return len(t.in) } | |
455 | |
456 // Out returns the type of the i'th function output parameter. | |
457 func (t *FuncType) Out(i int) Type { | |
458 if i < 0 || i >= len(t.out) { | |
459 return nil | |
460 } | |
461 return toType(*t.out[i]) | |
462 } | |
463 | |
464 // NumOut returns the number of function output parameters. | |
465 func (t *FuncType) NumOut() int { return len(t.out) } | |
466 | |
467 // Method returns the i'th method in the type's method set. | 622 // Method returns the i'th method in the type's method set. |
468 func (t *InterfaceType) Method(i int) (m Method) { | 623 func (t *interfaceType) Method(i int) (m Method) { |
469 if i < 0 || i >= len(t.methods) { | 624 if i < 0 || i >= len(t.methods) { |
470 return | 625 return |
471 } | 626 } |
472 p := &t.methods[i] | 627 p := &t.methods[i] |
473 m.Name = *p.name | 628 m.Name = *p.name |
474 if p.pkgPath != nil { | 629 if p.pkgPath != nil { |
475 m.PkgPath = *p.pkgPath | 630 m.PkgPath = *p.pkgPath |
476 } | 631 } |
477 » m.Type = toType(*p.typ).(*FuncType) | 632 » m.Type = toType(p.typ) |
478 return | 633 return |
479 } | 634 } |
480 | 635 |
481 // NumMethod returns the number of interface methods in the type's method set. | 636 // NumMethod returns the number of interface methods in the type's method set. |
482 func (t *InterfaceType) NumMethod() int { return len(t.methods) } | 637 func (t *interfaceType) NumMethod() int { return len(t.methods) } |
483 | |
484 // Key returns the map key type. | |
485 func (t *MapType) Key() Type { return toType(*t.key) } | |
486 | |
487 // Elem returns the map element type. | |
488 func (t *MapType) Elem() Type { return toType(*t.elem) } | |
489 | |
490 // Elem returns the pointer element type. | |
491 func (t *PtrType) Elem() Type { return toType(*t.elem) } | |
492 | |
493 // Elem returns the type of the slice's elements. | |
494 func (t *SliceType) Elem() Type { return toType(*t.elem) } | |
495 | 638 |
496 type StructField struct { | 639 type StructField struct { |
497 PkgPath string // empty for uppercase Name | 640 PkgPath string // empty for uppercase Name |
498 Name string | 641 Name string |
499 Type Type | 642 Type Type |
500 Tag string | 643 Tag string |
501 Offset uintptr | 644 Offset uintptr |
502 Index []int | 645 Index []int |
503 Anonymous bool | 646 Anonymous bool |
504 } | 647 } |
505 | 648 |
506 // Field returns the i'th struct field. | 649 // Field returns the i'th struct field. |
507 func (t *StructType) Field(i int) (f StructField) { | 650 func (t *structType) Field(i int) (f StructField) { |
508 if i < 0 || i >= len(t.fields) { | 651 if i < 0 || i >= len(t.fields) { |
509 return | 652 return |
510 } | 653 } |
511 p := t.fields[i] | 654 p := t.fields[i] |
512 » f.Type = toType(*p.typ) | 655 » f.Type = toType(p.typ) |
513 if p.name != nil { | 656 if p.name != nil { |
514 f.Name = *p.name | 657 f.Name = *p.name |
515 } else { | 658 } else { |
516 t := f.Type | 659 t := f.Type |
517 » » if pt, ok := t.(*PtrType); ok { | 660 » » if t.Kind() == Ptr { |
518 » » » t = pt.Elem() | 661 » » » t = t.Elem() |
519 } | 662 } |
520 f.Name = t.Name() | 663 f.Name = t.Name() |
521 f.Anonymous = true | 664 f.Anonymous = true |
522 } | 665 } |
523 if p.pkgPath != nil { | 666 if p.pkgPath != nil { |
524 f.PkgPath = *p.pkgPath | 667 f.PkgPath = *p.pkgPath |
525 } | 668 } |
526 if p.tag != nil { | 669 if p.tag != nil { |
527 f.Tag = *p.tag | 670 f.Tag = *p.tag |
528 } | 671 } |
529 f.Offset = p.offset | 672 f.Offset = p.offset |
530 f.Index = []int{i} | 673 f.Index = []int{i} |
531 return | 674 return |
532 } | 675 } |
533 | 676 |
534 // TODO(gri): Should there be an error/bool indicator if the index | 677 // TODO(gri): Should there be an error/bool indicator if the index |
535 // is wrong for FieldByIndex? | 678 // is wrong for FieldByIndex? |
536 | 679 |
537 // FieldByIndex returns the nested field corresponding to index. | 680 // FieldByIndex returns the nested field corresponding to index. |
538 func (t *StructType) FieldByIndex(index []int) (f StructField) { | 681 func (t *structType) FieldByIndex(index []int) (f StructField) { |
682 » f.Type = Type(t.toType()) | |
539 for i, x := range index { | 683 for i, x := range index { |
540 if i > 0 { | 684 if i > 0 { |
541 ft := f.Type | 685 ft := f.Type |
542 » » » if pt, ok := ft.(*PtrType); ok { | 686 » » » if ft.Kind() == Ptr { |
543 » » » » ft = pt.Elem() | 687 » » » » ft = ft.Elem() |
544 } | 688 } |
545 » » » if st, ok := ft.(*StructType); ok { | 689 » » » if ft.Kind() != Struct { |
546 » » » » t = st | 690 » » » » return StructField{} |
niemeyer
2011/04/04 13:52:35
Should we take the chance to make this panic rathe
rsc
2011/04/05 16:29:45
Done.
| |
547 » » » } else { | |
548 » » » » var f0 StructField | |
549 » » » » f = f0 | |
550 » » » » return | |
551 } | 691 } |
692 f.Type = ft | |
552 } | 693 } |
553 » » f = t.Field(x) | 694 » » f = f.Type.Field(x) |
554 } | 695 } |
555 return | 696 return |
556 } | 697 } |
557 | 698 |
558 const inf = 1 << 30 // infinity - no struct has that many nesting levels | 699 const inf = 1 << 30 // infinity - no struct has that many nesting levels |
559 | 700 |
560 func (t *StructType) fieldByNameFunc(match func(string) bool, mark map[*StructTy pe]bool, depth int) (ff StructField, fd int) { | 701 func (t *structType) fieldByNameFunc(match func(string) bool, mark map[*structTy pe]bool, depth int) (ff StructField, fd int) { |
561 fd = inf // field depth | 702 fd = inf // field depth |
562 | 703 |
563 if mark[t] { | 704 if mark[t] { |
564 // Struct already seen. | 705 // Struct already seen. |
565 return | 706 return |
566 } | 707 } |
567 mark[t] = true | 708 mark[t] = true |
568 | 709 |
569 var fi int // field index | 710 var fi int // field index |
570 n := 0 // number of matching fields at depth fd | 711 n := 0 // number of matching fields at depth fd |
571 L: | 712 L: |
572 for i := range t.fields { | 713 for i := range t.fields { |
573 f := t.Field(i) | 714 f := t.Field(i) |
574 d := inf | 715 d := inf |
575 switch { | 716 switch { |
576 case match(f.Name): | 717 case match(f.Name): |
577 // Matching top-level field. | 718 // Matching top-level field. |
578 d = depth | 719 d = depth |
579 case f.Anonymous: | 720 case f.Anonymous: |
580 ft := f.Type | 721 ft := f.Type |
581 » » » if pt, ok := ft.(*PtrType); ok { | 722 » » » if ft.Kind() == Ptr { |
582 » » » » ft = pt.Elem() | 723 » » » » ft = ft.Elem() |
583 } | 724 } |
584 switch { | 725 switch { |
585 case match(ft.Name()): | 726 case match(ft.Name()): |
586 // Matching anonymous top-level field. | 727 // Matching anonymous top-level field. |
587 d = depth | 728 d = depth |
588 case fd > depth: | 729 case fd > depth: |
589 // No top-level field yet; look inside nested st ructs. | 730 // No top-level field yet; look inside nested st ructs. |
590 » » » » if st, ok := ft.(*StructType); ok { | 731 » » » » if ft.Kind() == Struct { |
732 » » » » » st := (*structType)(unsafe.Pointer(ft.(* commonType))) | |
591 f, d = st.fieldByNameFunc(match, mark, d epth+1) | 733 f, d = st.fieldByNameFunc(match, mark, d epth+1) |
592 } | 734 } |
593 } | 735 } |
594 } | 736 } |
595 | 737 |
596 switch { | 738 switch { |
597 case d < fd: | 739 case d < fd: |
598 // Found field at shallower depth. | 740 // Found field at shallower depth. |
599 ff, fi, fd = f, i, d | 741 ff, fi, fd = f, i, d |
600 n = 1 | 742 n = 1 |
(...skipping 18 matching lines...) Expand all Loading... | |
619 // None or more than one matching field found. | 761 // None or more than one matching field found. |
620 fd = inf | 762 fd = inf |
621 } | 763 } |
622 | 764 |
623 mark[t] = false, false | 765 mark[t] = false, false |
624 return | 766 return |
625 } | 767 } |
626 | 768 |
627 // FieldByName returns the struct field with the given name | 769 // FieldByName returns the struct field with the given name |
628 // and a boolean to indicate if the field was found. | 770 // and a boolean to indicate if the field was found. |
629 func (t *StructType) FieldByName(name string) (f StructField, present bool) { | 771 func (t *structType) FieldByName(name string) (f StructField, present bool) { |
630 return t.FieldByNameFunc(func(s string) bool { return s == name }) | 772 return t.FieldByNameFunc(func(s string) bool { return s == name }) |
631 } | 773 } |
632 | 774 |
633 // FieldByNameFunc returns the struct field with a name that satisfies the | 775 // FieldByNameFunc returns the struct field with a name that satisfies the |
634 // match function and a boolean to indicate if the field was found. | 776 // match function and a boolean to indicate if the field was found. |
635 func (t *StructType) FieldByNameFunc(match func(string) bool) (f StructField, pr esent bool) { | 777 func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, pr esent bool) { |
636 » if ff, fd := t.fieldByNameFunc(match, make(map[*StructType]bool), 0); fd < inf { | 778 » if ff, fd := t.fieldByNameFunc(match, make(map[*structType]bool), 0); fd < inf { |
637 ff.Index = ff.Index[0 : fd+1] | 779 ff.Index = ff.Index[0 : fd+1] |
638 f, present = ff, true | 780 f, present = ff, true |
639 } | 781 } |
640 return | 782 return |
641 } | 783 } |
642 | 784 |
643 // NumField returns the number of struct fields. | |
644 func (t *StructType) NumField() int { return len(t.fields) } | |
645 | |
646 // Convert runtime type to reflect type. | 785 // Convert runtime type to reflect type. |
647 // Same memory layouts, different method sets. | 786 func toType(p *runtime.Type) Type { |
648 func toType(i interface{}) Type { | 787 » type hdr struct { |
649 » switch v := i.(type) { | 788 » » x interface{} |
650 » case nil: | 789 » » t commonType |
651 » » return nil | |
652 » case *runtime.BoolType: | |
653 » » return (*BoolType)(unsafe.Pointer(v)) | |
654 » case *runtime.FloatType: | |
655 » » return (*FloatType)(unsafe.Pointer(v)) | |
656 » case *runtime.ComplexType: | |
657 » » return (*ComplexType)(unsafe.Pointer(v)) | |
658 » case *runtime.IntType: | |
659 » » return (*IntType)(unsafe.Pointer(v)) | |
660 » case *runtime.StringType: | |
661 » » return (*StringType)(unsafe.Pointer(v)) | |
662 » case *runtime.UintType: | |
663 » » return (*UintType)(unsafe.Pointer(v)) | |
664 » case *runtime.UnsafePointerType: | |
665 » » return (*UnsafePointerType)(unsafe.Pointer(v)) | |
666 » case *runtime.ArrayType: | |
667 » » return (*ArrayType)(unsafe.Pointer(v)) | |
668 » case *runtime.ChanType: | |
669 » » return (*ChanType)(unsafe.Pointer(v)) | |
670 » case *runtime.FuncType: | |
671 » » return (*FuncType)(unsafe.Pointer(v)) | |
672 » case *runtime.InterfaceType: | |
673 » » return (*InterfaceType)(unsafe.Pointer(v)) | |
674 » case *runtime.MapType: | |
675 » » return (*MapType)(unsafe.Pointer(v)) | |
676 » case *runtime.PtrType: | |
677 » » return (*PtrType)(unsafe.Pointer(v)) | |
678 » case *runtime.SliceType: | |
679 » » return (*SliceType)(unsafe.Pointer(v)) | |
680 » case *runtime.StructType: | |
681 » » return (*StructType)(unsafe.Pointer(v)) | |
682 } | 790 } |
683 » println(i) | 791 » t := &(*hdr)(unsafe.Pointer(p)).t |
684 » panic("toType") | 792 » return t.toType() |
685 } | |
686 | |
687 // ArrayOrSliceType is the common interface implemented | |
688 // by both ArrayType and SliceType. | |
689 type ArrayOrSliceType interface { | |
690 » Type | |
691 » Elem() Type | |
692 » arrayOrSliceType() // Guarantees only Array and Slice implement this int erface. | |
693 } | 793 } |
694 | 794 |
695 // Typeof returns the reflection Type of the value in the interface{}. | 795 // Typeof returns the reflection Type of the value in the interface{}. |
696 func Typeof(i interface{}) Type { return toType(unsafe.Typeof(i)) } | 796 func Typeof(i interface{}) Type { |
797 » type hdr struct { | |
798 » » typ *byte | |
799 » » val *commonType | |
800 » } | |
801 » rt := unsafe.Typeof(i) | |
802 » t := (*(*hdr)(unsafe.Pointer(&rt))).val | |
803 » return t.toType() | |
804 } | |
697 | 805 |
698 // ptrMap is the cache for PtrTo. | 806 // ptrMap is the cache for PtrTo. |
699 var ptrMap struct { | 807 var ptrMap struct { |
700 sync.RWMutex | 808 sync.RWMutex |
701 » m map[Type]*PtrType | 809 » m map[*commonType]*ptrType |
702 } | |
703 | |
704 // runtimePtrType is the runtime layout for a *PtrType. | |
705 // The memory immediately before the *PtrType is always | |
706 // the canonical runtime.Type to be used for a *runtime.Type | |
707 // describing this PtrType. | |
708 type runtimePtrType struct { | |
709 » runtime.Type | |
710 » runtime.PtrType | |
711 } | 810 } |
712 | 811 |
713 // PtrTo returns the pointer type with element t. | 812 // PtrTo returns the pointer type with element t. |
714 // For example, if t represents type Foo, PtrTo(t) represents *Foo. | 813 // For example, if t represents type Foo, PtrTo(t) represents *Foo. |
715 func PtrTo(t Type) *PtrType { | 814 func PtrTo(t Type) Type { |
716 // If t records its pointer-to type, use it. | 815 // If t records its pointer-to type, use it. |
717 » ct := t.common() | 816 » ct := t.(*commonType) |
718 if p := ct.ptrToThis; p != nil { | 817 if p := ct.ptrToThis; p != nil { |
719 » » return toType(*p).(*PtrType) | 818 » » return toType(p) |
720 } | 819 } |
721 | 820 |
722 // Otherwise, synthesize one. | 821 // Otherwise, synthesize one. |
723 // This only happens for pointers with no methods. | 822 // This only happens for pointers with no methods. |
724 // We keep the mapping in a map on the side, because | 823 // We keep the mapping in a map on the side, because |
725 // this operation is rare and a separate map lets us keep | 824 // this operation is rare and a separate map lets us keep |
726 // the type structures in read-only memory. | 825 // the type structures in read-only memory. |
727 ptrMap.RLock() | 826 ptrMap.RLock() |
728 if m := ptrMap.m; m != nil { | 827 if m := ptrMap.m; m != nil { |
729 » » if p := m[t]; p != nil { | 828 » » if p := m[ct]; p != nil { |
730 ptrMap.RUnlock() | 829 ptrMap.RUnlock() |
731 » » » return p | 830 » » » return p.commonType.toType() |
732 } | 831 } |
733 } | 832 } |
734 ptrMap.RUnlock() | 833 ptrMap.RUnlock() |
735 ptrMap.Lock() | 834 ptrMap.Lock() |
736 if ptrMap.m == nil { | 835 if ptrMap.m == nil { |
737 » » ptrMap.m = make(map[Type]*PtrType) | 836 » » ptrMap.m = make(map[*commonType]*ptrType) |
738 } | 837 } |
739 » p := ptrMap.m[t] | 838 » p := ptrMap.m[ct] |
740 if p != nil { | 839 if p != nil { |
741 // some other goroutine won the race and created it | 840 // some other goroutine won the race and created it |
742 ptrMap.Unlock() | 841 ptrMap.Unlock() |
743 return p | 842 return p |
744 } | 843 } |
745 | 844 |
746 » // runtime.Type value is always right before type structure. | 845 » var rt struct { |
747 » // 2*ptrSize is size of interface header | 846 » » i runtime.Type |
748 » rt := (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - uintp tr(unsafe.Sizeof(runtime.Type(nil))))) | 847 » » ptrType |
848 » } | |
849 » rt.i = (*runtime.PtrType)(unsafe.Pointer(&rt.ptrType)) | |
749 | 850 |
750 » rp := new(runtimePtrType) | 851 » // initialize p using *byte's PtrType as a prototype. |
751 » rp.Type = &rp.PtrType | |
752 | |
753 » // initialize rp.PtrType using *byte's PtrType as a prototype. | |
754 // have to do assignment as PtrType, not runtime.PtrType, | 852 // have to do assignment as PtrType, not runtime.PtrType, |
755 // in order to write to unexported fields. | 853 // in order to write to unexported fields. |
756 » p = (*PtrType)(unsafe.Pointer(&rp.PtrType)) | 854 » p = &rt.ptrType |
757 » bp := (*PtrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.Pt rType))) | 855 » bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.Pt rType))) |
758 *p = *bp | 856 *p = *bp |
759 | 857 |
760 s := "*" + *ct.string | 858 s := "*" + *ct.string |
761 p.string = &s | 859 p.string = &s |
762 | 860 |
763 // For the type structures linked into the binary, the | 861 // For the type structures linked into the binary, the |
764 // compiler provides a good hash of the string. | 862 // compiler provides a good hash of the string. |
765 // Create a good hash for the new string by using | 863 // Create a good hash for the new string by using |
766 // the FNV-1 hash's mixing function to combine the | 864 // the FNV-1 hash's mixing function to combine the |
767 // old hash and the new "*". | 865 // old hash and the new "*". |
768 p.hash = ct.hash*16777619 ^ '*' | 866 p.hash = ct.hash*16777619 ^ '*' |
769 | 867 |
770 p.uncommonType = nil | 868 p.uncommonType = nil |
771 p.ptrToThis = nil | 869 p.ptrToThis = nil |
772 » p.elem = rt | 870 » p.elem = (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - ui ntptr(unsafe.Offsetof(rt.ptrType)))) |
773 | 871 |
774 » ptrMap.m[t] = (*PtrType)(unsafe.Pointer(&rp.PtrType)) | 872 » ptrMap.m[ct] = p |
775 ptrMap.Unlock() | 873 ptrMap.Unlock() |
776 » return p | 874 » return p.commonType.toType() |
777 } | 875 } |
OLD | NEW |