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