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