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