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