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