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