~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to contrib/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
ļ»æ//
2
 
// typespec.cs: Type specification
3
 
//
4
 
// Authors: Marek Safar (marek.safar@gmail.com)
5
 
//
6
 
// Dual licensed under the terms of the MIT X11 or GNU GPL
7
 
//
8
 
// Copyright 2010 Novell, Inc
9
 
// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
10
 
//
11
 
 
12
 
using System;
13
 
using System.Collections.Generic;
14
 
using System.Text;
15
 
 
16
 
#if STATIC
17
 
using MetaType = IKVM.Reflection.Type;
18
 
using IKVM.Reflection;
19
 
#else
20
 
using MetaType = System.Type;
21
 
using System.Reflection;
22
 
#endif
23
 
 
24
 
namespace Mono.CSharp
25
 
{
26
 
        public class TypeSpec : MemberSpec
27
 
        {
28
 
                protected MetaType info;
29
 
                protected MemberCache cache;
30
 
                protected IList<TypeSpec> ifaces;
31
 
                TypeSpec base_type;
32
 
 
33
 
                Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
34
 
 
35
 
                public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
36
 
 
37
 
#if !STATIC
38
 
                // Reflection Emit hacking
39
 
                static readonly Type TypeBuilder;
40
 
                static readonly Type GenericTypeBuilder;
41
 
 
42
 
                static TypeSpec ()
43
 
                {
44
 
                        var assembly = typeof (object).Assembly;
45
 
                        TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder");
46
 
                        GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass");
47
 
                        if (GenericTypeBuilder == null)
48
 
                                GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
49
 
                }
50
 
#endif
51
 
 
52
 
                public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers)
53
 
                        : base (kind, declaringType, definition, modifiers)
54
 
                {
55
 
                        this.declaringType = declaringType;
56
 
                        this.info = info;
57
 
 
58
 
                        if (definition != null && definition.TypeParametersCount > 0)
59
 
                                state |= StateFlags.IsGeneric;
60
 
                }
61
 
 
62
 
                #region Properties
63
 
 
64
 
                public override int Arity {
65
 
                        get {
66
 
                                return MemberDefinition.TypeParametersCount;
67
 
                        }
68
 
                }
69
 
 
70
 
                public virtual TypeSpec BaseType {
71
 
                        get {
72
 
                                return base_type;
73
 
                        }
74
 
                        set {
75
 
                                base_type = value;
76
 
                        }
77
 
                }
78
 
 
79
 
                public virtual BuiltinTypeSpec.Type BuiltinType {
80
 
                        get {
81
 
                                return BuiltinTypeSpec.Type.None;
82
 
                        }
83
 
                }
84
 
 
85
 
                public bool HasDynamicElement {
86
 
                        get {
87
 
                                return (state & StateFlags.HasDynamicElement) != 0;
88
 
                        }
89
 
                }
90
 
 
91
 
                public virtual IList<TypeSpec> Interfaces {
92
 
                        get {
93
 
                                return ifaces;
94
 
                        }
95
 
                        set {
96
 
                                ifaces = value;
97
 
                        }
98
 
                }
99
 
 
100
 
                public bool IsArray {
101
 
                        get {
102
 
                                return Kind == MemberKind.ArrayType;
103
 
                        }
104
 
                }
105
 
 
106
 
                public bool IsAttribute {
107
 
                        get {
108
 
                                if (!IsClass)
109
 
                                        return false;
110
 
 
111
 
                                var type = this;
112
 
                                do {
113
 
                                        if (type.BuiltinType == BuiltinTypeSpec.Type.Attribute)
114
 
                                                return true;
115
 
 
116
 
                                        if (type.IsGeneric)
117
 
                                                return false;
118
 
                                        
119
 
                                        type = type.base_type;
120
 
                                } while (type != null);
121
 
 
122
 
                                return false;
123
 
                        }
124
 
                }
125
 
 
126
 
                public bool IsInterface {
127
 
                        get {
128
 
                                return Kind == MemberKind.Interface;
129
 
                        }
130
 
                }
131
 
 
132
 
                public bool IsClass {
133
 
                        get {
134
 
                                return Kind == MemberKind.Class;
135
 
                        }
136
 
                }
137
 
 
138
 
                public bool IsConstantCompatible {
139
 
                        get {
140
 
                                if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
141
 
                                        return true;
142
 
 
143
 
                                switch (BuiltinType) {
144
 
                                case BuiltinTypeSpec.Type.Int:
145
 
                                case BuiltinTypeSpec.Type.UInt:
146
 
                                case BuiltinTypeSpec.Type.Long:
147
 
                                case BuiltinTypeSpec.Type.ULong:
148
 
                                case BuiltinTypeSpec.Type.Float:
149
 
                                case BuiltinTypeSpec.Type.Double:
150
 
                                case BuiltinTypeSpec.Type.Char:
151
 
                                case BuiltinTypeSpec.Type.Short:
152
 
                                case BuiltinTypeSpec.Type.Decimal:
153
 
                                case BuiltinTypeSpec.Type.Bool:
154
 
                                case BuiltinTypeSpec.Type.SByte:
155
 
                                case BuiltinTypeSpec.Type.Byte:
156
 
                                case BuiltinTypeSpec.Type.UShort:
157
 
                                case BuiltinTypeSpec.Type.Dynamic:
158
 
                                        return true;
159
 
                                }
160
 
 
161
 
                                return false;
162
 
                        }
163
 
                }
164
 
 
165
 
                public bool IsDelegate {
166
 
                        get {
167
 
                                return Kind == MemberKind.Delegate;
168
 
                        }
169
 
                }
170
 
 
171
 
                //
172
 
                // Returns true for instances of Expression<T>
173
 
                //
174
 
                public virtual bool IsExpressionTreeType {
175
 
                        get {
176
 
                                return false;
177
 
                        }
178
 
                        set {
179
 
                                state = value ? state | StateFlags.InflatedExpressionType : state & ~StateFlags.InflatedExpressionType;
180
 
                        }
181
 
                }
182
 
 
183
 
                public bool IsEnum {
184
 
                        get {
185
 
                                return Kind == MemberKind.Enum;
186
 
                        }
187
 
                }
188
 
 
189
 
                //
190
 
                // Returns true for instances of IList<T>, IEnumerable<T>, ICollection<T>
191
 
                //
192
 
                public virtual bool IsGenericIterateInterface {
193
 
                        get {
194
 
                                return false;
195
 
                        }
196
 
                        set {
197
 
                                state = value ? state | StateFlags.GenericIterateInterface : state & ~StateFlags.GenericIterateInterface;
198
 
                        }
199
 
                }
200
 
 
201
 
                //
202
 
                // Returns true for instances of System.Threading.Tasks.Task<T>
203
 
                //
204
 
                public virtual bool IsGenericTask {
205
 
                        get {
206
 
                                return false;
207
 
                        }
208
 
                        set {
209
 
                                state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask;
210
 
                        }
211
 
                }
212
 
 
213
 
                // TODO: Should probably do
214
 
                // IsGenericType -- recursive
215
 
                // HasTypeParameter -- non-recursive
216
 
                public bool IsGenericOrParentIsGeneric {
217
 
                        get {
218
 
                                var ts = this;
219
 
                                do {
220
 
                                        if (ts.IsGeneric)
221
 
                                                return true;
222
 
                                        ts = ts.declaringType;
223
 
                                } while (ts != null);
224
 
 
225
 
                                return false;
226
 
                        }
227
 
                }
228
 
 
229
 
                public bool IsGenericParameter {
230
 
                        get {
231
 
                                return Kind == MemberKind.TypeParameter;
232
 
                        }
233
 
                }
234
 
 
235
 
                //
236
 
                // Returns true for instances of Nullable<T>
237
 
                //
238
 
                public virtual bool IsNullableType {
239
 
                        get {
240
 
                                return false;
241
 
                        }
242
 
                        set {
243
 
                                state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType;
244
 
                        }
245
 
                }
246
 
 
247
 
                public bool IsNested {
248
 
                        get { return declaringType != null && Kind != MemberKind.TypeParameter; }
249
 
                }
250
 
 
251
 
                public bool IsPointer {
252
 
                        get {
253
 
                                return Kind == MemberKind.PointerType;
254
 
                        }
255
 
                }
256
 
 
257
 
                public bool IsSealed {
258
 
                        get { return (Modifiers & Modifiers.SEALED) != 0; }
259
 
                }
260
 
 
261
 
                public bool IsSpecialRuntimeType {
262
 
                        get {
263
 
                                return (state & StateFlags.SpecialRuntimeType) != 0;
264
 
                        }
265
 
                        set {
266
 
                                state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType;
267
 
                        }
268
 
                }
269
 
 
270
 
                public bool IsStruct {
271
 
                        get { 
272
 
                                return Kind == MemberKind.Struct;
273
 
                        }
274
 
                }
275
 
 
276
 
                public bool IsTypeBuilder {
277
 
                        get {
278
 
#if STATIC
279
 
                                return true;
280
 
#else
281
 
                                var meta = GetMetaInfo().GetType ();
282
 
                                return meta == TypeBuilder || meta == GenericTypeBuilder;
283
 
#endif
284
 
                        }
285
 
                }
286
 
 
287
 
                //
288
 
                // Whether a type is unmanaged. This is used by the unsafe code
289
 
                //
290
 
                public bool IsUnmanaged {
291
 
                        get {
292
 
                                if (IsPointer)
293
 
                                        return ((ElementTypeSpec) this).Element.IsUnmanaged;
294
 
 
295
 
                                var ds = MemberDefinition as TypeDefinition;
296
 
                                if (ds != null)
297
 
                                        return ds.IsUnmanagedType ();
298
 
 
299
 
                                if (Kind == MemberKind.Void)
300
 
                                        return true;
301
 
 
302
 
                                if (IsNested && DeclaringType.IsGenericOrParentIsGeneric)
303
 
                                        return false;
304
 
 
305
 
                                return IsValueType (this);
306
 
                        }
307
 
                }
308
 
 
309
 
                public MemberCache MemberCache {
310
 
                        get {
311
 
                                if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
312
 
                                        InitializeMemberCache (false);
313
 
 
314
 
                                return cache;
315
 
                        }
316
 
                        set {
317
 
                                if (cache != null)
318
 
                                        throw new InternalErrorException ("Membercache reset");
319
 
 
320
 
                                cache = value;
321
 
                        }
322
 
                }
323
 
 
324
 
                public MemberCache MemberCacheTypes {
325
 
                        get {
326
 
                                if (cache == null)
327
 
                                        InitializeMemberCache (true);
328
 
 
329
 
                                return cache;
330
 
                        }
331
 
                }       
332
 
 
333
 
                public new ITypeDefinition MemberDefinition {
334
 
                        get {
335
 
                                return (ITypeDefinition) definition;
336
 
                        }
337
 
                }
338
 
 
339
 
                // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
340
 
                // remove the property, YES IT WOULD !!!
341
 
                public virtual TypeSpec[] TypeArguments {
342
 
                        get { return TypeSpec.EmptyTypes; }
343
 
                }
344
 
 
345
 
                #endregion
346
 
 
347
 
                public bool AddInterface (TypeSpec iface)
348
 
                {
349
 
                        if ((state & StateFlags.InterfacesExpanded) != 0)
350
 
                                throw new InternalErrorException ("Modifying expanded interface list");
351
 
 
352
 
                        if (ifaces == null) {
353
 
                                ifaces = new List<TypeSpec> () { iface };
354
 
                                return true;
355
 
                        }
356
 
 
357
 
                        if (!ifaces.Contains (iface)) {
358
 
                                ifaces.Add (iface);
359
 
                                return true;
360
 
                        }
361
 
 
362
 
                        return false;
363
 
                }
364
 
 
365
 
                //
366
 
                // Special version used during type definition
367
 
                //
368
 
                public bool AddInterfaceDefined (TypeSpec iface)
369
 
                {
370
 
                        if (!AddInterface (iface))
371
 
                                return false;
372
 
 
373
 
                        //
374
 
                        // We can get into a situation where a type is inflated before
375
 
                        // its interfaces are resoved. Consider this situation
376
 
                        //
377
 
                        // class A<T> : X<A<int>>, IFoo {}
378
 
                        //
379
 
                        // When resolving base class of X`1 we inflate context type A`1
380
 
                        // All this happens before we even hit IFoo resolve. Without
381
 
                        // additional expansion any inside usage of A<T> would miss IFoo
382
 
                        // interface because it comes from early inflated TypeSpec
383
 
                        //
384
 
                        if (inflated_instances != null) {
385
 
                                foreach (var inflated in inflated_instances) {
386
 
                                        inflated.Value.AddInterface (iface);
387
 
                                }
388
 
                        }
389
 
 
390
 
                        return true;
391
 
                }
392
 
 
393
 
                //
394
 
                // Returns all type arguments, usefull for nested types
395
 
                //
396
 
                public static TypeSpec[] GetAllTypeArguments (TypeSpec type)
397
 
                {
398
 
                        IList<TypeSpec> targs = TypeSpec.EmptyTypes;
399
 
 
400
 
                        do {
401
 
                                if (type.Arity > 0) {
402
 
                                        if (targs.Count == 0) {
403
 
                                                targs = type.TypeArguments;
404
 
                                        } else {
405
 
                                                var list = targs as List<TypeSpec> ?? new List<TypeSpec> (targs);
406
 
                                                list.AddRange (type.TypeArguments);
407
 
                                                targs = list;
408
 
                                        }
409
 
                                }
410
 
 
411
 
                                type = type.declaringType;
412
 
                        } while (type != null);
413
 
 
414
 
                        return targs as TypeSpec[] ?? ((List<TypeSpec>) targs).ToArray ();
415
 
                }
416
 
 
417
 
                public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
418
 
                {
419
 
                        if (Kind != MemberKind.Class)
420
 
                                throw new InternalErrorException ();
421
 
 
422
 
                        if (!pa.IsDefined)
423
 
                                return Attribute.DefaultUsageAttribute;
424
 
 
425
 
                        AttributeUsageAttribute aua = null;
426
 
                        var type = this;
427
 
                        while (type != null) {
428
 
                                aua = type.MemberDefinition.GetAttributeUsage (pa);
429
 
                                if (aua != null)
430
 
                                        break;
431
 
 
432
 
                                type = type.BaseType;
433
 
                        }
434
 
 
435
 
                        return aua;
436
 
                }
437
 
 
438
 
                public virtual MetaType GetMetaInfo ()
439
 
                {
440
 
                        return info;
441
 
                }
442
 
 
443
 
                public virtual TypeSpec GetDefinition ()
444
 
                {
445
 
                        return this;
446
 
                }
447
 
 
448
 
                public override string GetSignatureForDocumentation ()
449
 
                {
450
 
                        StringBuilder sb = new StringBuilder ();
451
 
                        if (IsNested) {
452
 
                                sb.Append (DeclaringType.GetSignatureForDocumentation ());
453
 
                        } else {
454
 
                                sb.Append (MemberDefinition.Namespace);
455
 
                        }
456
 
 
457
 
                        if (sb.Length != 0)
458
 
                                sb.Append (".");
459
 
 
460
 
                        sb.Append (Name);
461
 
                        if (Arity > 0) {
462
 
                                if (this is InflatedTypeSpec) {
463
 
                                    sb.Append ("{");
464
 
                                    for (int i = 0; i < Arity; ++i) {
465
 
                                        if (i > 0)
466
 
                                            sb.Append (",");
467
 
 
468
 
                                        sb.Append (TypeArguments[i].GetSignatureForDocumentation ());
469
 
                                    }
470
 
                                    sb.Append ("}");
471
 
                                } else {
472
 
                                        sb.Append ("`");
473
 
                                        sb.Append (Arity.ToString ());
474
 
                                }
475
 
                        }
476
 
 
477
 
                        return sb.ToString ();
478
 
                }
479
 
 
480
 
                public string GetExplicitNameSignatureForDocumentation ()
481
 
                {
482
 
                        StringBuilder sb = new StringBuilder ();
483
 
                        if (IsNested) {
484
 
                                sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ());
485
 
                        } else if (MemberDefinition.Namespace != null) {
486
 
                                sb.Append (MemberDefinition.Namespace.Replace ('.', '#'));
487
 
                        }
488
 
 
489
 
                        if (sb.Length != 0)
490
 
                                sb.Append ("#");
491
 
 
492
 
                        sb.Append (Name);
493
 
                        if (Arity > 0) {
494
 
                                sb.Append ("{");
495
 
                                for (int i = 0; i < Arity; ++i) {
496
 
                                        if (i > 0)
497
 
                                                sb.Append (",");
498
 
 
499
 
                                        sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ());
500
 
                                }
501
 
                                sb.Append ("}");
502
 
                        }
503
 
 
504
 
                        return sb.ToString ();
505
 
                }
506
 
 
507
 
                public override string GetSignatureForError ()
508
 
                {
509
 
                        string s;
510
 
 
511
 
                        if (IsNested) {
512
 
                                s = DeclaringType.GetSignatureForError ();
513
 
                        } else if (MemberDefinition is AnonymousTypeClass) {
514
 
                                return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
515
 
                        } else {
516
 
                                s = MemberDefinition.Namespace;
517
 
                        }
518
 
 
519
 
                        if (!string.IsNullOrEmpty (s))
520
 
                                s += ".";
521
 
 
522
 
                        return s + Name + GetTypeNameSignature ();
523
 
                }
524
 
 
525
 
                public string GetSignatureForErrorIncludingAssemblyName ()
526
 
                {
527
 
                        return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName);
528
 
                }
529
 
 
530
 
                protected virtual string GetTypeNameSignature ()
531
 
                {
532
 
                        if (!IsGeneric)
533
 
                                return null;
534
 
 
535
 
                        return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
536
 
                }
537
 
 
538
 
                public bool ImplementsInterface (TypeSpec iface, bool variantly)
539
 
                {
540
 
                        var t = this;
541
 
                        do {
542
 
                                var ifaces = t.Interfaces;
543
 
                                if (ifaces != null) {
544
 
                                        for (int i = 0; i < ifaces.Count; ++i) {
545
 
                                                if (TypeSpecComparer.IsEqual (ifaces[i], iface))
546
 
                                                        return true;
547
 
 
548
 
                                                if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface))
549
 
                                                        return true;
550
 
                                        }
551
 
                                }
552
 
 
553
 
                                // TODO: Why is it needed when we do it during import
554
 
                                t = t.BaseType;
555
 
                        } while (t != null);
556
 
 
557
 
                        return false;
558
 
                }
559
 
 
560
 
                protected virtual void InitializeMemberCache (bool onlyTypes)
561
 
                {
562
 
                        try {
563
 
                                MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
564
 
                        } catch (Exception e) {
565
 
                                throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ());
566
 
                        }
567
 
 
568
 
                        if (onlyTypes)
569
 
                                state |= StateFlags.PendingMemberCacheMembers;
570
 
                        else
571
 
                                state &= ~StateFlags.PendingMemberCacheMembers;
572
 
                }
573
 
 
574
 
                //
575
 
                // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
576
 
                // comparison is used to hide differences between `object' and `dynamic' for generic
577
 
                // types. Should not be used for comparisons where G<object> != G<dynamic>
578
 
                //
579
 
                public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
580
 
                {
581
 
                        if (dynamicIsObject && baseClass.IsGeneric) {
582
 
                                //
583
 
                                // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
584
 
                                //
585
 
                                // class B : A<object> {}
586
 
                                //
587
 
                                type = type.BaseType;
588
 
                                while (type != null) {
589
 
                                        if (TypeSpecComparer.IsEqual (type, baseClass))
590
 
                                                return true;
591
 
 
592
 
                                        type = type.BaseType;
593
 
                                }
594
 
 
595
 
                                return false;
596
 
                        }
597
 
 
598
 
                        while (type != null) {
599
 
                                type = type.BaseType;
600
 
                                if (type == baseClass)
601
 
                                        return true;
602
 
                        }
603
 
 
604
 
                        return false;
605
 
                }
606
 
 
607
 
                public static bool IsReferenceType (TypeSpec t)
608
 
                {
609
 
                        switch (t.Kind) {
610
 
                        case MemberKind.TypeParameter:
611
 
                                return ((TypeParameterSpec) t).IsReferenceType;
612
 
                        case MemberKind.Struct:
613
 
                        case MemberKind.Enum:
614
 
                        case MemberKind.Void:
615
 
                                return false;
616
 
                        case MemberKind.InternalCompilerType:
617
 
                                //
618
 
                                // Null is considered to be a reference type
619
 
                                //                      
620
 
                                return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
621
 
                        default:
622
 
                                return true;
623
 
                        }
624
 
                }
625
 
 
626
 
                public static bool IsValueType (TypeSpec t)
627
 
                {
628
 
                        switch (t.Kind) {
629
 
                        case MemberKind.TypeParameter:
630
 
                                return ((TypeParameterSpec) t).IsValueType;
631
 
                        case MemberKind.Struct:
632
 
                        case MemberKind.Enum:
633
 
                                return true;
634
 
                        default:
635
 
                                return false;
636
 
                        }
637
 
                }
638
 
 
639
 
                public override MemberSpec InflateMember (TypeParameterInflator inflator)
640
 
                {
641
 
                        var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
642
 
 
643
 
                        //
644
 
                        // When inflating nested type from inside the type instance will be same
645
 
                        // because type parameters are same for all nested types
646
 
                        //
647
 
                        if (DeclaringType == inflator.TypeInstance) {
648
 
                                return MakeGenericType (inflator.Context, targs);
649
 
                        }
650
 
 
651
 
                        return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs);
652
 
                }
653
 
 
654
 
                public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs)
655
 
                {
656
 
                        if (targs.Length == 0 && !IsNested)
657
 
                                throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
658
 
 
659
 
                        InflatedTypeSpec instance;
660
 
 
661
 
                        if (inflated_instances == null) {
662
 
                                inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
663
 
 
664
 
                                if (IsNested) {
665
 
                                        instance = this as InflatedTypeSpec;
666
 
                                        if (instance != null) {
667
 
                                                //
668
 
                                                // Nested types could be inflated on already inflated instances
669
 
                                                // Caching this type ensured we are using same instance for
670
 
                                                // inside/outside inflation using local type parameters
671
 
                                                //
672
 
                                                inflated_instances.Add (TypeArguments, instance);
673
 
                                        }
674
 
                                }
675
 
                        }
676
 
 
677
 
                        if (!inflated_instances.TryGetValue (targs, out instance)) {
678
 
                                if (GetDefinition () != this && !IsNested)
679
 
                                        throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
680
 
                                                GetSignatureForError ());
681
 
 
682
 
                                instance = new InflatedTypeSpec (context, this, declaringType, targs);
683
 
                                inflated_instances.Add (targs, instance);
684
 
                        }
685
 
 
686
 
                        return instance;
687
 
                }
688
 
 
689
 
                public virtual TypeSpec Mutate (TypeParameterMutator mutator)
690
 
                {
691
 
                        return this;
692
 
                }
693
 
 
694
 
                public override List<TypeSpec> ResolveMissingDependencies ()
695
 
                {
696
 
                        List<TypeSpec> missing = null;
697
 
 
698
 
                        if (Kind == MemberKind.MissingType) {
699
 
                                missing = new List<TypeSpec> ();
700
 
                                missing.Add (this);
701
 
                                return missing;
702
 
                        }
703
 
 
704
 
                        foreach (var targ in TypeArguments) {
705
 
                                if (targ.Kind == MemberKind.MissingType) {
706
 
                                        if (missing == null)
707
 
                                                missing = new List<TypeSpec> ();
708
 
 
709
 
                                        missing.Add (targ);
710
 
                                }
711
 
                        }
712
 
 
713
 
                        if (Interfaces != null) {
714
 
                                foreach (var iface in Interfaces) {
715
 
                                        if (iface.Kind == MemberKind.MissingType) {
716
 
                                                if (missing == null)
717
 
                                                        missing = new List<TypeSpec> ();
718
 
 
719
 
                                                missing.Add (iface);
720
 
                                        }
721
 
                                }
722
 
                        }
723
 
 
724
 
                        if (MemberDefinition.TypeParametersCount > 0) {
725
 
                                foreach (var tp in MemberDefinition.TypeParameters) {
726
 
                                        var tp_missing = tp.GetMissingDependencies ();
727
 
                                        if (tp_missing != null) {
728
 
                                                if (missing == null)
729
 
                                                        missing = new List<TypeSpec> ();
730
 
 
731
 
                                                missing.AddRange (tp_missing);
732
 
                                        }
733
 
                                }
734
 
                        }
735
 
 
736
 
                        if (missing != null || BaseType == null)
737
 
                                return missing;
738
 
 
739
 
                        return BaseType.ResolveMissingDependencies ();
740
 
                }
741
 
 
742
 
                public void SetMetaInfo (MetaType info)
743
 
                {
744
 
                        if (this.info != null)
745
 
                                throw new InternalErrorException ("MetaInfo reset");
746
 
 
747
 
                        this.info = info;
748
 
                }
749
 
 
750
 
                public void SetExtensionMethodContainer ()
751
 
                {
752
 
                        modifiers |= Modifiers.METHOD_EXTENSION;
753
 
                }
754
 
        }
755
 
 
756
 
        public sealed class BuiltinTypeSpec : TypeSpec
757
 
        {
758
 
                public enum Type
759
 
                {
760
 
                        None = 0,
761
 
 
762
 
                        // Ordered carefully for fast compares
763
 
                        FirstPrimitive = 1,
764
 
                        Bool = 1,
765
 
                        Byte = 2,
766
 
                        SByte = 3,
767
 
                        Char = 4,
768
 
                        Short = 5,
769
 
                        UShort = 6,
770
 
                        Int = 7,
771
 
                        UInt = 8,
772
 
                        Long = 9,
773
 
                        ULong = 10,
774
 
                        Float = 11,
775
 
                        Double = 12,
776
 
                        LastPrimitive = 12,
777
 
                        Decimal = 13,
778
 
 
779
 
                        IntPtr = 14,
780
 
                        UIntPtr = 15,
781
 
 
782
 
                        Object = 16,
783
 
                        Dynamic = 17,
784
 
                        String = 18,
785
 
                        Type = 19,
786
 
 
787
 
                        ValueType = 20,
788
 
                        Enum = 21,
789
 
                        Delegate = 22,
790
 
                        MulticastDelegate = 23,
791
 
                        Array = 24,
792
 
 
793
 
                        IEnumerator,
794
 
                        IEnumerable,
795
 
                        IDisposable,
796
 
                        Exception,
797
 
                        Attribute,
798
 
                        Other,
799
 
                }
800
 
 
801
 
                readonly Type type;
802
 
                readonly string ns;
803
 
                readonly string name;
804
 
 
805
 
                public BuiltinTypeSpec (MemberKind kind, string ns, string name, Type builtinKind)
806
 
                        : base (kind, null, null, null, Modifiers.PUBLIC)
807
 
                {
808
 
                        this.type = builtinKind;
809
 
                        this.ns = ns;
810
 
                        this.name = name;
811
 
                }
812
 
 
813
 
                public BuiltinTypeSpec (string name, Type builtinKind)
814
 
                        : this (MemberKind.InternalCompilerType, "", name, builtinKind)
815
 
                {
816
 
                        // Make all internal types CLS-compliant, non-obsolete, compact
817
 
                        state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
818
 
                }
819
 
 
820
 
                #region Properties
821
 
 
822
 
                public override int Arity {
823
 
                        get {
824
 
                                return 0;
825
 
                        }
826
 
                }
827
 
 
828
 
                public override BuiltinTypeSpec.Type BuiltinType {
829
 
                        get {
830
 
                                return type;
831
 
                        }
832
 
                }
833
 
 
834
 
                public string FullName {
835
 
                        get {
836
 
                                return ns + '.' + name;
837
 
                        }
838
 
                }
839
 
 
840
 
                public override string Name {
841
 
                        get {
842
 
                                return name;
843
 
                        }
844
 
                }
845
 
 
846
 
                public string Namespace {
847
 
                        get {
848
 
                                return ns;
849
 
                        }
850
 
                }
851
 
 
852
 
                #endregion
853
 
 
854
 
                public static bool IsPrimitiveType (TypeSpec type)
855
 
                {
856
 
                        return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.LastPrimitive;
857
 
                }
858
 
 
859
 
                public static bool IsPrimitiveTypeOrDecimal (TypeSpec type)
860
 
                {
861
 
                        return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.Decimal;
862
 
                }
863
 
 
864
 
                public override string GetSignatureForError ()
865
 
                {
866
 
                        switch (Name) {
867
 
                        case "Int32": return "int";
868
 
                        case "Int64": return "long";
869
 
                        case "String": return "string";
870
 
                        case "Boolean": return "bool";
871
 
                        case "Void": return "void";
872
 
                        case "Object": return "object";
873
 
                        case "UInt32": return "uint";
874
 
                        case "Int16": return "short";
875
 
                        case "UInt16": return "ushort";
876
 
                        case "UInt64": return "ulong";
877
 
                        case "Single": return "float";
878
 
                        case "Double": return "double";
879
 
                        case "Decimal": return "decimal";
880
 
                        case "Char": return "char";
881
 
                        case "Byte": return "byte";
882
 
                        case "SByte": return "sbyte";
883
 
                        }
884
 
 
885
 
                        if (ns.Length == 0)
886
 
                                return name;
887
 
 
888
 
                        return FullName;
889
 
                }
890
 
 
891
 
                //
892
 
                // Returns the size of type if known, otherwise, 0
893
 
                //
894
 
                public static int GetSize (TypeSpec type)
895
 
                {
896
 
                        switch (type.BuiltinType) {
897
 
                        case Type.Int:
898
 
                        case Type.UInt:
899
 
                        case Type.Float:
900
 
                                return 4;
901
 
                        case Type.Long:
902
 
                        case Type.ULong:
903
 
                        case Type.Double:
904
 
                                return 8;
905
 
                        case Type.Byte:
906
 
                        case Type.SByte:
907
 
                        case Type.Bool:
908
 
                                return 1;
909
 
                        case Type.Short:
910
 
                        case Type.Char:
911
 
                        case Type.UShort:
912
 
                                return 2;
913
 
                        case Type.Decimal:
914
 
                                return 16;
915
 
                        default:
916
 
                                return 0;
917
 
                        }
918
 
                }
919
 
 
920
 
                public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod)
921
 
                {
922
 
                        this.definition = td;
923
 
                        this.info = type;
924
 
                        this.modifiers |= (mod & ~Modifiers.AccessibilityMask);
925
 
                }
926
 
 
927
 
                public void SetDefinition (TypeSpec ts)
928
 
                {
929
 
                        this.definition = ts.MemberDefinition;
930
 
                        this.info = ts.GetMetaInfo ();
931
 
                        this.BaseType = ts.BaseType;
932
 
                        this.Interfaces = ts.Interfaces;
933
 
                        this.modifiers = ts.Modifiers;
934
 
                }
935
 
        }
936
 
 
937
 
        static class TypeSpecComparer
938
 
        {
939
 
                //
940
 
                // Does strict reference comparion only
941
 
                //
942
 
                public static readonly DefaultImpl Default = new DefaultImpl ();
943
 
 
944
 
                public class DefaultImpl : IEqualityComparer<TypeSpec[]>
945
 
                {
946
 
                        #region IEqualityComparer<TypeSpec[]> Members
947
 
 
948
 
                        bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
949
 
                        {
950
 
                                if (x == y)
951
 
                                        return true;
952
 
 
953
 
                                if (x.Length != y.Length)
954
 
                                        return false;
955
 
 
956
 
                                for (int i = 0; i < x.Length; ++i)
957
 
                                        if (x[i] != y[i])
958
 
                                                return false;
959
 
 
960
 
                                return true;
961
 
                        }
962
 
 
963
 
                        int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
964
 
                        {
965
 
                                int hash = 0;
966
 
                                for (int i = 0; i < obj.Length; ++i)
967
 
                                        hash = (hash << 5) - hash + obj[i].GetHashCode ();
968
 
 
969
 
                                return hash;
970
 
                        }
971
 
 
972
 
                        #endregion
973
 
                }
974
 
 
975
 
                //
976
 
                // When comparing type signature of overrides or overloads
977
 
                // this version tolerates different MVARs at same position
978
 
                //
979
 
                public static class Override
980
 
                {
981
 
                        public static bool IsEqual (TypeSpec a, TypeSpec b)
982
 
                        {
983
 
                                if (a == b)
984
 
                                        return true;
985
 
 
986
 
                                //
987
 
                                // Consider the following example:
988
 
                                //
989
 
                                //     public abstract class A
990
 
                                //     {
991
 
                                //        public abstract T Foo<T>();
992
 
                                //     }
993
 
                                //
994
 
                                //     public class B : A
995
 
                                //     {
996
 
                                //        public override U Foo<T>() { return default (U); }
997
 
                                //     }
998
 
                                //
999
 
                                // Here, `T' and `U' are method type parameters from different methods
1000
 
                                // (A.Foo and B.Foo), so both `==' and Equals() will fail.
1001
 
                                //
1002
 
                                // However, since we're determining whether B.Foo() overrides A.Foo(),
1003
 
                                // we need to do a signature based comparision and consider them equal.
1004
 
                                //
1005
 
 
1006
 
                                var tp_a = a as TypeParameterSpec;
1007
 
                                if (tp_a != null) {
1008
 
                                        var tp_b = b as TypeParameterSpec;
1009
 
                                        return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
1010
 
                                }
1011
 
 
1012
 
                                var ac_a = a as ArrayContainer;
1013
 
                                if (ac_a != null) {
1014
 
                                        var ac_b = b as ArrayContainer;
1015
 
                                        return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
1016
 
                                }
1017
 
 
1018
 
                                if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1019
 
                                        return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
1020
 
 
1021
 
                                if (a.MemberDefinition != b.MemberDefinition)
1022
 
                                        return false;
1023
 
 
1024
 
                                do {
1025
 
                                        for (int i = 0; i < a.TypeArguments.Length; ++i) {
1026
 
                                                if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
1027
 
                                                        return false;
1028
 
                                        }
1029
 
 
1030
 
                                        a = a.DeclaringType;
1031
 
                                        b = b.DeclaringType;
1032
 
                                } while (a != null);
1033
 
 
1034
 
                                return true;
1035
 
                        }
1036
 
 
1037
 
                        //
1038
 
                        // Compares unordered arrays
1039
 
                        //
1040
 
                        public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
1041
 
                        {
1042
 
                                if (a == b)
1043
 
                                        return true;
1044
 
 
1045
 
                                if (a == null || b == null || a.Length != b.Length)
1046
 
                                        return false;
1047
 
 
1048
 
                                for (int ai = 0; ai < a.Length; ++ai) {
1049
 
                                        bool found = false;
1050
 
                                        for (int bi = 0; bi < b.Length; ++bi) {
1051
 
                                                if (IsEqual (a[ai], b[bi])) {
1052
 
                                                        found = true;
1053
 
                                                        break;
1054
 
                                                }
1055
 
                                        }
1056
 
 
1057
 
                                        if (!found)
1058
 
                                                return false;
1059
 
                                }
1060
 
 
1061
 
                                return true;
1062
 
                        }
1063
 
 
1064
 
                        public static bool IsEqual (AParametersCollection a, AParametersCollection b)
1065
 
                        {
1066
 
                                if (a == b)
1067
 
                                        return true;
1068
 
 
1069
 
                                if (a.Count != b.Count)
1070
 
                                        return false;
1071
 
 
1072
 
                                for (int i = 0; i < a.Count; ++i) {
1073
 
                                        if (!IsEqual (a.Types[i], b.Types[i]))
1074
 
                                                return false;
1075
 
 
1076
 
                                        if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
1077
 
                                                return false;
1078
 
                                }
1079
 
 
1080
 
                                return true;
1081
 
                        }
1082
 
                }
1083
 
 
1084
 
                //
1085
 
                // Type variance equality comparison
1086
 
                //
1087
 
                public static class Variant
1088
 
                {
1089
 
                        public static bool IsEqual (TypeSpec type1, TypeSpec type2)
1090
 
                        {
1091
 
                                if (!type1.IsGeneric || !type2.IsGeneric)
1092
 
                                        return false;
1093
 
 
1094
 
                                var target_type_def = type2.MemberDefinition;
1095
 
                                if (type1.MemberDefinition != target_type_def)
1096
 
                                        return false;
1097
 
 
1098
 
                                var t1_targs = type1.TypeArguments;
1099
 
                                var t2_targs = type2.TypeArguments;
1100
 
                                var targs_definition = target_type_def.TypeParameters;
1101
 
 
1102
 
                                if (!type1.IsInterface && !type1.IsDelegate) {
1103
 
                                        return false;
1104
 
                                }
1105
 
 
1106
 
                                for (int i = 0; i < targs_definition.Length; ++i) {
1107
 
                                        if (TypeSpecComparer.IsEqual (t1_targs[i], t2_targs[i]))
1108
 
                                                continue;
1109
 
 
1110
 
                                        Variance v = targs_definition[i].Variance;
1111
 
                                        if (v == Variance.None) {
1112
 
                                                return false;
1113
 
                                        }
1114
 
 
1115
 
                                        if (v == Variance.Covariant) {
1116
 
                                                if (!Convert.ImplicitReferenceConversionExists (t1_targs[i], t2_targs[i]))
1117
 
                                                        return false;
1118
 
                                        } else if (!Convert.ImplicitReferenceConversionExists (t2_targs[i], t1_targs[i])) {
1119
 
                                                return false;
1120
 
                                        }
1121
 
                                }
1122
 
 
1123
 
                                return true;
1124
 
                        }
1125
 
                }
1126
 
 
1127
 
                //
1128
 
                // Checks whether two generic instances may become equal for some
1129
 
                // particular instantiation (26.3.1).
1130
 
                //
1131
 
                public static class Unify
1132
 
                {
1133
 
                        //
1134
 
                        // Either @a or @b must be generic type
1135
 
                        //
1136
 
                        public static bool IsEqual (TypeSpec a, TypeSpec b)
1137
 
                        {
1138
 
                                if (a.MemberDefinition != b.MemberDefinition) {
1139
 
                                        var base_ifaces = a.Interfaces;
1140
 
                                        if (base_ifaces != null) {
1141
 
                                                foreach (var base_iface in base_ifaces) {
1142
 
                                                        if (base_iface.Arity > 0 && IsEqual (base_iface, b))
1143
 
                                                                return true;
1144
 
                                                }
1145
 
                                        }
1146
 
 
1147
 
                                        return false;
1148
 
                                }
1149
 
 
1150
 
                                var ta = a.TypeArguments;
1151
 
                                var tb = b.TypeArguments;
1152
 
                                for (int i = 0; i < ta.Length; i++) {
1153
 
                                        if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
1154
 
                                                return false;
1155
 
                                }
1156
 
 
1157
 
                                return true;
1158
 
                        }
1159
 
 
1160
 
                        static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
1161
 
                        {
1162
 
                                TypeSpec[] targs = type.TypeArguments;
1163
 
                                for (int i = 0; i < targs.Length; i++) {
1164
 
                                        if (tparam == targs[i])
1165
 
                                                return true;
1166
 
 
1167
 
                                        if (ContainsTypeParameter (tparam, targs[i]))
1168
 
                                                return true;
1169
 
                                }
1170
 
 
1171
 
                                return false;
1172
 
                        }
1173
 
 
1174
 
                        /// <summary>
1175
 
                        ///   Check whether `a' and `b' may become equal generic types.
1176
 
                        ///   The algorithm to do that is a little bit complicated.
1177
 
                        /// </summary>
1178
 
                        static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
1179
 
                        {
1180
 
                                if (a.IsGenericParameter) {
1181
 
                                        //
1182
 
                                        // If a is an array of a's type, they may never
1183
 
                                        // become equal.
1184
 
                                        //
1185
 
                                        if (b.IsArray)
1186
 
                                                return false;
1187
 
 
1188
 
                                        //
1189
 
                                        // If b is a generic parameter or an actual type,
1190
 
                                        // they may become equal:
1191
 
                                        //
1192
 
                                        //    class X<T,U> : I<T>, I<U>
1193
 
                                        //    class X<T> : I<T>, I<float>
1194
 
                                        // 
1195
 
                                        if (b.IsGenericParameter)
1196
 
                                                return a != b && a.DeclaringType == b.DeclaringType;
1197
 
 
1198
 
                                        //
1199
 
                                        // We're now comparing a type parameter with a
1200
 
                                        // generic instance.  They may become equal unless
1201
 
                                        // the type parameter appears anywhere in the
1202
 
                                        // generic instance:
1203
 
                                        //
1204
 
                                        //    class X<T,U> : I<T>, I<X<U>>
1205
 
                                        //        -> error because you could instanciate it as
1206
 
                                        //           X<X<int>,int>
1207
 
                                        //
1208
 
                                        //    class X<T> : I<T>, I<X<T>> -> ok
1209
 
                                        //
1210
 
 
1211
 
                                        return !ContainsTypeParameter (a, b);
1212
 
                                }
1213
 
 
1214
 
                                if (b.IsGenericParameter)
1215
 
                                        return MayBecomeEqualGenericTypes (b, a);
1216
 
 
1217
 
                                //
1218
 
                                // At this point, neither a nor b are a type parameter.
1219
 
                                //
1220
 
                                // If one of them is a generic instance, compare them (if the
1221
 
                                // other one is not a generic instance, they can never
1222
 
                                // become equal).
1223
 
                                //
1224
 
                                if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
1225
 
                                        return IsEqual (a, b);
1226
 
 
1227
 
                                //
1228
 
                                // If both of them are arrays.
1229
 
                                //
1230
 
                                var a_ac = a as ArrayContainer;
1231
 
                                if (a_ac != null) {
1232
 
                                        var b_ac = b as ArrayContainer;
1233
 
                                        if (b_ac == null || a_ac.Rank != b_ac.Rank)
1234
 
                                                return false;
1235
 
 
1236
 
                                        return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
1237
 
                                }
1238
 
 
1239
 
                                //
1240
 
                                // Ok, two ordinary types.
1241
 
                                //
1242
 
                                return false;
1243
 
                        }
1244
 
                }
1245
 
 
1246
 
                public static bool Equals (TypeSpec[] x, TypeSpec[] y)
1247
 
                {
1248
 
                        if (x == y)
1249
 
                                return true;
1250
 
 
1251
 
                        if (x.Length != y.Length)
1252
 
                                return false;
1253
 
 
1254
 
                        for (int i = 0; i < x.Length; ++i)
1255
 
                                if (!IsEqual (x[i], y[i]))
1256
 
                                        return false;
1257
 
 
1258
 
                        return true;
1259
 
                }
1260
 
 
1261
 
                //
1262
 
                // Identity type conversion
1263
 
                //
1264
 
                // Default reference comparison, it has to be used when comparing
1265
 
                // two possible dynamic/internal types
1266
 
                //
1267
 
                public static bool IsEqual (TypeSpec a, TypeSpec b)
1268
 
                {
1269
 
                        if (a == b) {
1270
 
                                // This also rejects dynamic == dynamic
1271
 
                                return a.Kind != MemberKind.InternalCompilerType || a.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
1272
 
                        }
1273
 
 
1274
 
                        if (a == null || b == null)
1275
 
                                return false;
1276
 
 
1277
 
                        if (a.IsArray) {
1278
 
                                var a_a = (ArrayContainer) a;
1279
 
                                var b_a = b as ArrayContainer;
1280
 
                                if (b_a == null)
1281
 
                                        return false;
1282
 
 
1283
 
                                return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element);
1284
 
                        }
1285
 
 
1286
 
                        if (!a.IsGeneric || !b.IsGeneric) {
1287
 
                                //
1288
 
                                // object and dynamic are considered equivalent there is an identity conversion
1289
 
                                // between object and dynamic, and between constructed types that are the same
1290
 
                                // when replacing all occurences of dynamic with object.
1291
 
                                //
1292
 
                                if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1293
 
                                        return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
1294
 
 
1295
 
                                return false;
1296
 
                        }
1297
 
 
1298
 
                        if (a.MemberDefinition != b.MemberDefinition)
1299
 
                                return false;
1300
 
 
1301
 
                        do {
1302
 
                                if (!Equals (a.TypeArguments, b.TypeArguments))
1303
 
                                        return false;
1304
 
 
1305
 
                                a = a.DeclaringType;
1306
 
                                b = b.DeclaringType;
1307
 
                        } while (a != null);
1308
 
 
1309
 
                        return true;
1310
 
                }
1311
 
        }
1312
 
 
1313
 
        public interface ITypeDefinition : IMemberDefinition
1314
 
        {
1315
 
                IAssemblyDefinition DeclaringAssembly { get; }
1316
 
                string Namespace { get; }
1317
 
                bool IsPartial { get; }
1318
 
                int TypeParametersCount { get; }
1319
 
                TypeParameterSpec[] TypeParameters { get; }
1320
 
 
1321
 
                TypeSpec GetAttributeCoClass ();
1322
 
                string GetAttributeDefaultMember ();
1323
 
                AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
1324
 
                bool IsInternalAsPublic (IAssemblyDefinition assembly);
1325
 
                void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
1326
 
        }
1327
 
 
1328
 
        class InternalType : TypeSpec, ITypeDefinition
1329
 
        {
1330
 
                public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
1331
 
                public static readonly InternalType Arglist = new InternalType ("__arglist");
1332
 
                public static readonly InternalType MethodGroup = new InternalType ("method group");
1333
 
                public static readonly InternalType NullLiteral = new InternalType ("null");
1334
 
                public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
1335
 
                public static readonly InternalType Namespace = new InternalType ("<namespace>");
1336
 
                public static readonly InternalType ErrorType = new InternalType ("<error>");
1337
 
 
1338
 
                readonly string name;
1339
 
 
1340
 
                InternalType (string name)
1341
 
                        : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
1342
 
                {
1343
 
                        this.name = name;
1344
 
                        this.definition = this;
1345
 
                        cache = MemberCache.Empty;
1346
 
 
1347
 
                        // Make all internal types CLS-compliant, non-obsolete
1348
 
                        state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
1349
 
                }
1350
 
 
1351
 
                #region Properties
1352
 
 
1353
 
                public override int Arity {
1354
 
                        get {
1355
 
                                return 0;
1356
 
                        }
1357
 
                }
1358
 
 
1359
 
                IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1360
 
                        get {
1361
 
                                throw new NotImplementedException ();
1362
 
                        }
1363
 
                }
1364
 
 
1365
 
                bool IMemberDefinition.IsImported {
1366
 
                        get {
1367
 
                                return false;
1368
 
                        }
1369
 
                }
1370
 
 
1371
 
                bool ITypeDefinition.IsPartial {
1372
 
                        get {
1373
 
                                return false;
1374
 
                        }
1375
 
                }
1376
 
 
1377
 
                public override string Name {
1378
 
                        get {
1379
 
                                return name;
1380
 
                        }
1381
 
                }
1382
 
 
1383
 
                string ITypeDefinition.Namespace {
1384
 
                        get {
1385
 
                                return null;
1386
 
                        }
1387
 
                }
1388
 
 
1389
 
                int ITypeDefinition.TypeParametersCount {
1390
 
                        get {
1391
 
                                return 0;
1392
 
                        }
1393
 
                }
1394
 
 
1395
 
                TypeParameterSpec[] ITypeDefinition.TypeParameters {
1396
 
                        get {
1397
 
                                return null;
1398
 
                        }
1399
 
                }
1400
 
 
1401
 
                #endregion
1402
 
 
1403
 
                public override string GetSignatureForError ()
1404
 
                {
1405
 
                        return name;
1406
 
                }
1407
 
 
1408
 
                #region ITypeDefinition Members
1409
 
 
1410
 
                TypeSpec ITypeDefinition.GetAttributeCoClass ()
1411
 
                {
1412
 
                        return null;
1413
 
                }
1414
 
 
1415
 
                string ITypeDefinition.GetAttributeDefaultMember ()
1416
 
                {
1417
 
                        return null;
1418
 
                }
1419
 
 
1420
 
                AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
1421
 
                {
1422
 
                        return null;
1423
 
                }
1424
 
 
1425
 
                bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1426
 
                {
1427
 
                        throw new NotImplementedException ();
1428
 
                }
1429
 
 
1430
 
                void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1431
 
                {
1432
 
                        throw new NotImplementedException ();
1433
 
                }
1434
 
 
1435
 
                string[] IMemberDefinition.ConditionalConditions ()
1436
 
                {
1437
 
                        return null;
1438
 
                }
1439
 
 
1440
 
                ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
1441
 
                {
1442
 
                        return null;
1443
 
                }
1444
 
 
1445
 
                bool? IMemberDefinition.CLSAttributeValue {
1446
 
                        get {
1447
 
                                return null;
1448
 
                        }
1449
 
                }
1450
 
 
1451
 
                void IMemberDefinition.SetIsAssigned ()
1452
 
                {
1453
 
                }
1454
 
 
1455
 
                void IMemberDefinition.SetIsUsed ()
1456
 
                {
1457
 
                }
1458
 
 
1459
 
                #endregion
1460
 
        }
1461
 
 
1462
 
        public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1463
 
        {
1464
 
                protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info)
1465
 
                        : base (kind, element.DeclaringType, null, info, element.Modifiers)
1466
 
                {
1467
 
                        this.Element = element;
1468
 
 
1469
 
                        state &= ~SharedStateFlags;
1470
 
                        state |= (element.state & SharedStateFlags);
1471
 
 
1472
 
                        if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1473
 
                                state |= StateFlags.HasDynamicElement;
1474
 
 
1475
 
                        // Has to use its own type definition instead of just element definition to
1476
 
                        // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1477
 
                        this.definition = this;
1478
 
 
1479
 
                        cache = MemberCache.Empty;
1480
 
                }
1481
 
 
1482
 
                #region Properties
1483
 
 
1484
 
                public TypeSpec Element { get; private set; }
1485
 
 
1486
 
                bool ITypeDefinition.IsPartial {
1487
 
                        get {
1488
 
                                return false;
1489
 
                        }
1490
 
                }
1491
 
 
1492
 
                public override string Name {
1493
 
                        get {
1494
 
                                throw new NotSupportedException ();
1495
 
                        }
1496
 
                }
1497
 
 
1498
 
                #endregion
1499
 
 
1500
 
                public override ObsoleteAttribute GetAttributeObsolete ()
1501
 
                {
1502
 
                        return Element.GetAttributeObsolete ();
1503
 
                }
1504
 
 
1505
 
                protected virtual string GetPostfixSignature ()
1506
 
                {
1507
 
                        return null;
1508
 
                }
1509
 
 
1510
 
                public override string GetSignatureForDocumentation ()
1511
 
                {
1512
 
                        return Element.GetSignatureForDocumentation () + GetPostfixSignature ();
1513
 
                }
1514
 
 
1515
 
                public override string GetSignatureForError ()
1516
 
                {
1517
 
                        return Element.GetSignatureForError () + GetPostfixSignature ();
1518
 
                }
1519
 
 
1520
 
                public override TypeSpec Mutate (TypeParameterMutator mutator)
1521
 
                {
1522
 
                        var me = Element.Mutate (mutator);
1523
 
                        if (me == Element)
1524
 
                                return this;
1525
 
 
1526
 
                        var mutated = (ElementTypeSpec) MemberwiseClone ();
1527
 
                        mutated.Element = me;
1528
 
                        mutated.info = null;
1529
 
                        return mutated;
1530
 
                }
1531
 
 
1532
 
                #region ITypeDefinition Members
1533
 
 
1534
 
                IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1535
 
                        get {
1536
 
                                return Element.MemberDefinition.DeclaringAssembly;
1537
 
                        }
1538
 
                }
1539
 
 
1540
 
                bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1541
 
                {
1542
 
                        return Element.MemberDefinition.IsInternalAsPublic (assembly);
1543
 
                }
1544
 
 
1545
 
                public string Namespace {
1546
 
                        get { throw new NotImplementedException (); }
1547
 
                }
1548
 
 
1549
 
                public int TypeParametersCount {
1550
 
                        get {
1551
 
                                return 0;
1552
 
                        }
1553
 
                }
1554
 
 
1555
 
                public TypeParameterSpec[] TypeParameters {
1556
 
                        get {
1557
 
                                throw new NotSupportedException ();
1558
 
                        }
1559
 
                }
1560
 
 
1561
 
                public TypeSpec GetAttributeCoClass ()
1562
 
                {
1563
 
                        return Element.MemberDefinition.GetAttributeCoClass ();
1564
 
                }
1565
 
 
1566
 
                public string GetAttributeDefaultMember ()
1567
 
                {
1568
 
                        return Element.MemberDefinition.GetAttributeDefaultMember ();
1569
 
                }
1570
 
 
1571
 
                public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1572
 
                {
1573
 
                        Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1574
 
                }
1575
 
 
1576
 
                public bool IsImported {
1577
 
                        get {
1578
 
                                return Element.MemberDefinition.IsImported;
1579
 
                        }
1580
 
                }
1581
 
 
1582
 
                public string[] ConditionalConditions ()
1583
 
                {
1584
 
                        return Element.MemberDefinition.ConditionalConditions ();
1585
 
                }
1586
 
 
1587
 
                bool? IMemberDefinition.CLSAttributeValue {
1588
 
                        get {
1589
 
                                return Element.MemberDefinition.CLSAttributeValue;
1590
 
                        }
1591
 
                }
1592
 
 
1593
 
                public void SetIsAssigned ()
1594
 
                {
1595
 
                        Element.MemberDefinition.SetIsAssigned ();
1596
 
                }
1597
 
 
1598
 
                public void SetIsUsed ()
1599
 
                {
1600
 
                        Element.MemberDefinition.SetIsUsed ();
1601
 
                }
1602
 
 
1603
 
                #endregion
1604
 
        }
1605
 
 
1606
 
        public class ArrayContainer : ElementTypeSpec
1607
 
        {
1608
 
                public struct TypeRankPair : IEquatable<TypeRankPair>
1609
 
                {
1610
 
                        TypeSpec ts;
1611
 
                        int rank;
1612
 
 
1613
 
                        public TypeRankPair (TypeSpec ts, int rank)
1614
 
                        {
1615
 
                                this.ts = ts;
1616
 
                                this.rank = rank;
1617
 
                        }
1618
 
 
1619
 
                        public override int GetHashCode ()
1620
 
                        {
1621
 
                                return ts.GetHashCode () ^ rank.GetHashCode ();
1622
 
                        }
1623
 
 
1624
 
                        #region IEquatable<Tuple<T1,T2>> Members
1625
 
 
1626
 
                        public bool Equals (TypeRankPair other)
1627
 
                        {
1628
 
                                return other.ts == ts && other.rank == rank;
1629
 
                        }
1630
 
 
1631
 
                        #endregion
1632
 
                }
1633
 
 
1634
 
                readonly int rank;
1635
 
                readonly ModuleContainer module;
1636
 
 
1637
 
                private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
1638
 
                        : base (MemberKind.ArrayType, element, null)
1639
 
                {
1640
 
                        this.module = module;
1641
 
                        this.rank = rank;
1642
 
                }
1643
 
 
1644
 
                public int Rank {
1645
 
                        get {
1646
 
                                return rank;
1647
 
                        }
1648
 
                }
1649
 
 
1650
 
                public MethodInfo GetConstructor ()
1651
 
                {
1652
 
                        var mb = module.Builder;
1653
 
 
1654
 
                        var arg_types = new MetaType[rank];
1655
 
                        for (int i = 0; i < rank; i++)
1656
 
                                arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1657
 
 
1658
 
                        var ctor = mb.GetArrayMethod (
1659
 
                                GetMetaInfo (), Constructor.ConstructorName,
1660
 
                                CallingConventions.HasThis,
1661
 
                                null, arg_types);
1662
 
 
1663
 
                        return ctor;
1664
 
                }
1665
 
 
1666
 
                public MethodInfo GetAddressMethod ()
1667
 
                {
1668
 
                        var mb = module.Builder;
1669
 
 
1670
 
                        var arg_types = new MetaType[rank];
1671
 
                        for (int i = 0; i < rank; i++)
1672
 
                                arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1673
 
 
1674
 
                        var address = mb.GetArrayMethod (
1675
 
                                GetMetaInfo (), "Address",
1676
 
                                CallingConventions.HasThis | CallingConventions.Standard,
1677
 
                                ReferenceContainer.MakeType (module, Element).GetMetaInfo (), arg_types);
1678
 
 
1679
 
                        return address;
1680
 
                }
1681
 
 
1682
 
                public MethodInfo GetGetMethod ()
1683
 
                {
1684
 
                        var mb = module.Builder;
1685
 
 
1686
 
                        var arg_types = new MetaType[rank];
1687
 
                        for (int i = 0; i < rank; i++)
1688
 
                                arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1689
 
 
1690
 
                        var get = mb.GetArrayMethod (
1691
 
                                GetMetaInfo (), "Get",
1692
 
                                CallingConventions.HasThis | CallingConventions.Standard,
1693
 
                                Element.GetMetaInfo (), arg_types);
1694
 
 
1695
 
                        return get;
1696
 
                }
1697
 
 
1698
 
                public MethodInfo GetSetMethod ()
1699
 
                {
1700
 
                        var mb = module.Builder;
1701
 
 
1702
 
                        var arg_types = new MetaType[rank + 1];
1703
 
                        for (int i = 0; i < rank; i++)
1704
 
                                arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1705
 
 
1706
 
                        arg_types[rank] = Element.GetMetaInfo ();
1707
 
 
1708
 
                        var set = mb.GetArrayMethod (
1709
 
                                GetMetaInfo (), "Set",
1710
 
                                CallingConventions.HasThis | CallingConventions.Standard,
1711
 
                                module.Compiler.BuiltinTypes.Void.GetMetaInfo (), arg_types);
1712
 
 
1713
 
                        return set;
1714
 
                }
1715
 
 
1716
 
                public override MetaType GetMetaInfo ()
1717
 
                {
1718
 
                        if (info == null) {
1719
 
                                if (rank == 1)
1720
 
                                        info = Element.GetMetaInfo ().MakeArrayType ();
1721
 
                                else
1722
 
                                        info = Element.GetMetaInfo ().MakeArrayType (rank);
1723
 
                        }
1724
 
 
1725
 
                        return info;
1726
 
                }
1727
 
 
1728
 
                protected override string GetPostfixSignature()
1729
 
                {
1730
 
                        return GetPostfixSignature (rank);
1731
 
                }
1732
 
 
1733
 
                public static string GetPostfixSignature (int rank)
1734
 
                {
1735
 
                        StringBuilder sb = new StringBuilder ();
1736
 
                        sb.Append ("[");
1737
 
                        for (int i = 1; i < rank; i++) {
1738
 
                                sb.Append (",");
1739
 
                        }
1740
 
                        sb.Append ("]");
1741
 
 
1742
 
                        return sb.ToString ();
1743
 
                }
1744
 
 
1745
 
                public override string GetSignatureForDocumentation ()
1746
 
                {
1747
 
                        StringBuilder sb = new StringBuilder ();
1748
 
                        GetElementSignatureForDocumentation (sb);
1749
 
                        return sb.ToString ();
1750
 
                }
1751
 
 
1752
 
                void GetElementSignatureForDocumentation (StringBuilder sb)
1753
 
                {
1754
 
                        var ac = Element as ArrayContainer;
1755
 
                        if (ac == null)
1756
 
                                sb.Append (Element.GetSignatureForDocumentation ());
1757
 
                        else
1758
 
                                ac.GetElementSignatureForDocumentation (sb);
1759
 
 
1760
 
                        sb.Append ("[");
1761
 
                        for (int i = 1; i < rank; i++) {
1762
 
                                if (i == 1)
1763
 
                                        sb.Append ("0:");
1764
 
 
1765
 
                                sb.Append (",0:");
1766
 
                        }
1767
 
                        sb.Append ("]");
1768
 
                }
1769
 
 
1770
 
                public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)
1771
 
                {
1772
 
                        return MakeType (module, element, 1);
1773
 
                }
1774
 
 
1775
 
                public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank)
1776
 
                {
1777
 
                        ArrayContainer ac;
1778
 
                        var key = new TypeRankPair (element, rank);
1779
 
                        if (!module.ArrayTypesCache.TryGetValue (key, out ac)) {
1780
 
                                ac = new ArrayContainer (module, element, rank) {
1781
 
                                        BaseType = module.Compiler.BuiltinTypes.Array
1782
 
                                };
1783
 
 
1784
 
                                module.ArrayTypesCache.Add (key, ac);
1785
 
                        }
1786
 
 
1787
 
                        return ac;
1788
 
                }
1789
 
        }
1790
 
 
1791
 
        class ReferenceContainer : ElementTypeSpec
1792
 
        {
1793
 
                private ReferenceContainer (TypeSpec element)
1794
 
                        : base (MemberKind.Class, element, null)        // TODO: Kind.Class is most likely wrong
1795
 
                {
1796
 
                }
1797
 
 
1798
 
                public override MetaType GetMetaInfo ()
1799
 
                {
1800
 
                        if (info == null) {
1801
 
                                info = Element.GetMetaInfo ().MakeByRefType ();
1802
 
                        }
1803
 
 
1804
 
                        return info;
1805
 
                }
1806
 
 
1807
 
                public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element)
1808
 
                {
1809
 
                        ReferenceContainer pc;
1810
 
                        if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) {
1811
 
                                pc = new ReferenceContainer (element);
1812
 
                                module.ReferenceTypesCache.Add (element, pc);
1813
 
                        }
1814
 
 
1815
 
                        return pc;
1816
 
                }
1817
 
        }
1818
 
 
1819
 
        class PointerContainer : ElementTypeSpec
1820
 
        {
1821
 
                private PointerContainer (TypeSpec element)
1822
 
                        : base (MemberKind.PointerType, element, null)
1823
 
                {
1824
 
                        // It's never CLS-Compliant
1825
 
                        state &= ~StateFlags.CLSCompliant_Undetected;
1826
 
                }
1827
 
 
1828
 
                public override MetaType GetMetaInfo ()
1829
 
                {
1830
 
                        if (info == null) {
1831
 
                                info = Element.GetMetaInfo ().MakePointerType ();
1832
 
                        }
1833
 
 
1834
 
                        return info;
1835
 
                }
1836
 
 
1837
 
                protected override string GetPostfixSignature()
1838
 
                {
1839
 
                        return "*";
1840
 
                }
1841
 
 
1842
 
                public static PointerContainer MakeType (ModuleContainer module, TypeSpec element)
1843
 
                {
1844
 
                        PointerContainer pc;
1845
 
                        if (!module.PointerTypesCache.TryGetValue (element, out pc)) {
1846
 
                                pc = new PointerContainer (element);
1847
 
                                module.PointerTypesCache.Add (element, pc);
1848
 
                        }
1849
 
 
1850
 
                        return pc;
1851
 
                }
1852
 
        }
1853
 
}