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