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