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

« back to all changes in this revision

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