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