2010-07-05 Atsushi Enomoto <atsushi@ximian.com>
[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 //
10
11 using System;
12 using System.Collections.Generic;
13 using System.Text;
14 using System.Linq;
15
16 namespace Mono.CSharp
17 {
18         public class TypeSpec : MemberSpec
19         {
20                 protected Type info;
21                 protected MemberCache cache;
22                 protected IList<TypeSpec> ifaces;
23                 TypeSpec base_type;
24
25                 Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
26
27                 public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
28
29                 // Reflection Emit hacking
30                 static Type TypeBuilder;
31                 static Type GenericTypeBuilder;
32
33                 static TypeSpec ()
34                 {
35                         var assembly = typeof (object).Assembly;
36                         TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder");
37                         GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass");
38                         if (GenericTypeBuilder == null)
39                                 GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
40                 }
41
42                 public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, Type info, Modifiers modifiers)
43                         : base (kind, declaringType, definition, modifiers)
44                 {
45                         this.declaringType = declaringType;
46                         this.info = info;
47
48                         if (definition != null && definition.TypeParametersCount > 0)
49                                 state |= StateFlags.IsGeneric;
50                 }
51
52                 #region Properties
53
54                 public override int Arity {
55                         get {
56                                 return MemberDefinition.TypeParametersCount;
57                         }
58                 }
59
60                 public virtual TypeSpec BaseType {
61                         get {
62                                 return base_type;
63                         }
64                         set {
65                                 base_type = value;
66                         }
67                 }
68
69                 public virtual IList<TypeSpec> Interfaces {
70                         get {
71                                 return ifaces;
72                         }
73                         set {
74                                 ifaces = value;
75                         }
76                 }
77
78                 public bool IsArray {
79                         get {
80                                 return Kind == MemberKind.ArrayType;
81                         }
82                 }
83
84                 public bool IsAttribute {
85                         get {
86                                 if (!IsClass)
87                                         return false;
88
89                                 var type = this;
90                                 do {
91                                         if (type.IsGeneric)
92                                                 return false;
93
94                                         if (type == TypeManager.attribute_type)
95                                                 return true;
96                                         
97                                         type = type.base_type;
98                                 } while (type != null);
99
100                                 return false;
101                         }
102                 }
103
104                 public bool IsInterface {
105                         get {
106                                 return Kind == MemberKind.Interface;
107                         }
108                 }
109
110                 public bool IsClass {
111                         get {
112                                 return Kind == MemberKind.Class;
113                         }
114                 }
115
116                 public bool IsConstantCompatible {
117                         get {
118                                 if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
119                                         return true;
120
121                                 return TypeManager.IsPrimitiveType (this) || this == TypeManager.decimal_type || this == InternalType.Dynamic;
122                         }
123                 }
124
125                 public bool IsDelegate {
126                         get {
127                                 return Kind == MemberKind.Delegate;
128                         }
129                 }
130
131                 public bool IsEnum {
132                         get { return Kind == MemberKind.Enum; }
133                 }
134
135                 // TODO: Should probably do
136                 // IsGenericType -- recursive
137                 // HasTypeParameter -- non-recursive
138                 public bool IsGenericOrParentIsGeneric {
139                         get {
140                                 var ts = this;
141                                 do {
142                                         if (ts.IsGeneric)
143                                                 return true;
144                                         ts = ts.declaringType;
145                                 } while (ts != null);
146
147                                 return false;
148                         }
149                 }
150
151                 public bool IsGenericParameter {
152                         get { return Kind == MemberKind.TypeParameter; }
153                 }
154
155                 public bool IsNested {
156                         get { return declaringType != null && Kind != MemberKind.TypeParameter; }
157                 }
158
159                 public bool IsPointer {
160                         get {
161                                 return Kind == MemberKind.PointerType;
162                         }
163                 }
164
165                 public bool IsSealed {
166                         get { return (Modifiers & Modifiers.SEALED) != 0; }
167                 }
168
169                 public bool IsStruct {
170                         get { 
171                                 return Kind == MemberKind.Struct;
172                         }
173                 }
174
175                 public bool IsTypeBuilder {
176                         get {
177                                 var meta = GetMetaInfo().GetType ();
178                                 return meta == TypeBuilder || meta == GenericTypeBuilder;
179                         }
180                 }
181
182                 public MemberCache MemberCache {
183                         get {
184                                 if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
185                                         InitializeMemberCache (false);
186
187                                 return cache;
188                         }
189                         set {
190                                 if (cache != null)
191                                         throw new InternalErrorException ("Membercache reset");
192
193                                 cache = value;
194                         }
195                 }
196
197                 public virtual MemberCache MemberCacheTypes {
198                         get {
199                                 return MemberCache;
200                         }
201                 }       
202
203                 public new ITypeDefinition MemberDefinition {
204                         get {
205                                 return (ITypeDefinition) definition;
206                         }
207                 }
208
209                 // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
210                 // remove the property, YES IT WOULD !!!
211                 public virtual TypeSpec[] TypeArguments {
212                         get { return TypeSpec.EmptyTypes; }
213                 }
214
215                 #endregion
216
217                 public bool AddInterface (TypeSpec iface)
218                 {
219                         if ((state & StateFlags.InterfacesExpanded) != 0)
220                                 throw new InternalErrorException ("Modifying expanded interface list");
221
222                         if (ifaces == null) {
223                                 ifaces = new List<TypeSpec> () { iface };
224                                 return true;
225                         }
226
227                         if (!ifaces.Contains (iface)) {
228                                 ifaces.Add (iface);
229                                 return true;
230                         }
231
232                         return false;
233                 }
234
235                 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
236                 {
237                         if (Kind != MemberKind.Class)
238                                 throw new InternalErrorException ();
239
240                         if (!pa.IsDefined)
241                                 return Attribute.DefaultUsageAttribute;
242
243                         AttributeUsageAttribute aua = null;
244                         var type = this;
245                         while (type != null) {
246                                 aua = type.MemberDefinition.GetAttributeUsage (pa);
247                                 if (aua != null)
248                                         break;
249
250                                 type = type.BaseType;
251                         }
252
253                         return aua;
254                 }
255
256                 public virtual Type GetMetaInfo ()
257                 {
258                         return info;
259                 }
260
261                 public virtual TypeSpec GetDefinition ()
262                 {
263                         return this;
264                 }
265
266                 public override string GetSignatureForError ()
267                 {
268                         string s;
269
270                         if (IsNested) {
271                                 s = DeclaringType.GetSignatureForError ();
272                         } else {
273                                 s = MemberDefinition.Namespace;
274                         }
275
276                         if (!string.IsNullOrEmpty (s))
277                                 s += ".";
278
279                         return s + Name + GetTypeNameSignature ();
280                 }
281
282                 protected virtual string GetTypeNameSignature ()
283                 {
284                         if (!IsGeneric)
285                                 return null;
286
287                         return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
288                 }
289
290                 public bool ImplementsInterface (TypeSpec iface)
291                 {
292                         var t = this;
293                         do {
294                                 if (t.Interfaces != null) {     // TODO: Try t.iface
295                                         foreach (TypeSpec i in t.Interfaces) {
296                                                 if (i == iface || TypeSpecComparer.Variant.IsEqual (i, iface))
297                                                         return true;
298                                         }
299                                 }
300
301                                 t = t.BaseType;
302                         } while (t != null);
303
304                         return false;
305                 }
306
307                 protected virtual void InitializeMemberCache (bool onlyTypes)
308                 {
309                         //
310                         // Not interested in members of nested private types
311                         //
312                         if (IsPrivate) {
313                                 cache = new MemberCache (0);
314                         } else {
315                                 cache = MemberDefinition.LoadMembers (this);
316                         }
317                 }
318
319                 public override MemberSpec InflateMember (TypeParameterInflator inflator)
320                 {
321                         var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
322
323                         //
324                         // When inflating nested type from inside the type instance will be same
325                         // because type parameters are same for all nested types
326                         //
327                         if (DeclaringType == inflator.TypeInstance)
328                                 return MakeGenericType (targs);
329
330                         return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
331                 }
332
333                 public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
334                 {
335                         if (targs.Length == 0 && !IsNested)
336                                 throw new ArgumentException ("Empty type arguments");
337
338                         InflatedTypeSpec instance;
339
340                         if (inflated_instances == null)
341                                 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
342
343                         if (!inflated_instances.TryGetValue (targs, out instance)) {
344                                 if (GetDefinition () != this && !IsNested)
345                                         throw new InternalErrorException ("Only type definition or nested non-inflated types can be used to call MakeGenericType");
346
347                                 instance = new InflatedTypeSpec (this, declaringType, targs);
348                                 inflated_instances.Add (targs, instance);
349                         }
350
351                         return instance;
352                 }
353
354                 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
355                 {
356                         return this;
357                 }
358
359                 public void SetMetaInfo (Type info)
360                 {
361                         if (this.info != null)
362                                 throw new InternalErrorException ("MetaInfo reset");
363
364                         this.info = info;
365                 }
366
367                 public void SetExtensionMethodContainer ()
368                 {
369                         modifiers |= Modifiers.METHOD_EXTENSION;
370                 }
371         }
372
373         public class PredefinedTypeSpec : TypeSpec
374         {
375                 string name;
376                 string ns;
377
378                 public PredefinedTypeSpec (MemberKind kind, string ns, string name)
379                         : base (kind, null, null, null, Modifiers.PUBLIC)
380                 {
381                         this.name = name;
382                         this.ns = ns;
383                 }
384
385                 public override int Arity {
386                         get {
387                                 return 0;
388                         }
389                 }
390
391                 public override string Name {
392                         get {
393                                 return name;
394                         }
395                 }
396
397                 public string Namespace {
398                         get {
399                                 return ns;
400                         }
401                 }
402
403                 public override string GetSignatureForError ()
404                 {
405                         switch (name) {
406                         case "Int32": return "int";
407                         case "Int64": return "long";
408                         case "String": return "string";
409                         case "Boolean": return "bool";
410                         case "Void": return "void";
411                         case "Object": return "object";
412                         case "UInt32": return "uint";
413                         case "Int16": return "short";
414                         case "UInt16": return "ushort";
415                         case "UInt64": return "ulong";
416                         case "Single": return "float";
417                         case "Double": return "double";
418                         case "Decimal": return "decimal";
419                         case "Char": return "char";
420                         case "Byte": return "byte";
421                         case "SByte": return "sbyte";
422                         }
423
424                         return ns + "." + name;
425                 }
426
427                 public void SetDefinition (ITypeDefinition td, Type type)
428                 {
429                         this.definition = td;
430                         this.info = type;
431                 }
432
433                 public void SetDefinition (TypeSpec ts)
434                 {
435                         this.definition = ts.MemberDefinition;
436                         this.info = ts.GetMetaInfo ();
437                         this.BaseType = ts.BaseType;
438                         this.Interfaces = ts.Interfaces;
439                 }
440         }
441
442         static class TypeSpecComparer
443         {
444                 //
445                 // Default reference comparison
446                 //
447                 public static readonly DefaultImpl Default = new DefaultImpl ();
448
449                 public class DefaultImpl : IEqualityComparer<TypeSpec[]>, IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>
450                 {
451                         #region IEqualityComparer<TypeSpec[]> Members
452
453                         public bool Equals (TypeSpec[] x, TypeSpec[] y)
454                         {
455                                 if (x.Length != y.Length)
456                                         return false;
457
458                                 if (x == y)
459                                         return true;
460
461                                 for (int i = 0; i < x.Length; ++i)
462                                         if (x[i] != y[i])
463                                                 return false;
464
465                                 return true;
466                         }
467
468                         public int GetHashCode (TypeSpec[] obj)
469                         {
470                                 int hash = 0;
471                                 for (int i = 0; i < obj.Length; ++i)
472                                         hash = (hash << 5) - hash + obj[i].GetHashCode ();
473
474                                 return hash;
475                         }
476
477                         #endregion
478
479                         #region IEqualityComparer<Tuple<TypeSpec,TypeSpec[]>> Members
480
481                         bool IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>.Equals (Tuple<TypeSpec, TypeSpec[]> x, Tuple<TypeSpec, TypeSpec[]> y)
482                         {
483                                 return Equals (x.Item2, y.Item2) && x.Item1 == y.Item1;
484                         }
485
486                         int IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>.GetHashCode (Tuple<TypeSpec, TypeSpec[]> obj)
487                         {
488                                 return GetHashCode (obj.Item2) ^ obj.Item1.GetHashCode ();
489                         }
490
491                         #endregion
492                 }
493
494                 //
495                 // When comparing type signature of overrides or overloads
496                 // this version tolerates different MVARs at same position
497                 //
498                 public static class Override
499                 {
500                         public static bool IsEqual (TypeSpec a, TypeSpec b)
501                         {
502                                 if (a == b)
503                                         return true;
504
505                                 //
506                                 // Consider the following example:
507                                 //
508                                 //     public abstract class A
509                                 //     {
510                                 //        public abstract T Foo<T>();
511                                 //     }
512                                 //
513                                 //     public class B : A
514                                 //     {
515                                 //        public override U Foo<T>() { return default (U); }
516                                 //     }
517                                 //
518                                 // Here, `T' and `U' are method type parameters from different methods
519                                 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
520                                 //
521                                 // However, since we're determining whether B.Foo() overrides A.Foo(),
522                                 // we need to do a signature based comparision and consider them equal.
523                                 //
524
525                                 var tp_a = a as TypeParameterSpec;
526                                 if (tp_a != null) {
527                                         var tp_b = b as TypeParameterSpec;
528                                         return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
529                                 }
530
531                                 if (a.TypeArguments.Length != b.TypeArguments.Length)
532                                         return false;
533
534                                 if (a.TypeArguments.Length != 0) {
535                                         if (a.MemberDefinition != b.MemberDefinition)
536                                                 return false;
537
538                                         for (int i = 0; i < a.TypeArguments.Length; ++i) {
539                                                 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
540                                                         return false;
541                                         }
542
543                                         return true;
544                                 }
545
546                                 var ac_a = a as ArrayContainer;
547                                 if (ac_a != null) {
548                                         var ac_b = b as ArrayContainer;
549                                         return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
550                                 }
551
552                                 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
553                                         return b == TypeManager.object_type || a == TypeManager.object_type;
554
555                                 return false;
556                         }
557
558                         //
559                         // Compares unordered arrays
560                         //
561                         public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
562                         {
563                                 if (a == b)
564                                         return true;
565
566                                 if (a == null || b == null || a.Length != b.Length)
567                                         return false;
568
569                                 for (int ai = 0; ai < a.Length; ++ai) {
570                                         bool found = false;
571                                         for (int bi = 0; bi < b.Length; ++bi) {
572                                                 if (IsEqual (a[ai], b[bi])) {
573                                                         found = true;
574                                                         break;
575                                                 }
576                                         }
577
578                                         if (!found)
579                                                 return false;
580                                 }
581
582                                 return true;
583                         }
584
585                         public static bool IsEqual (AParametersCollection a, AParametersCollection b)
586                         {
587                                 if (a == b)
588                                         return true;
589
590                                 if (a.Count != b.Count)
591                                         return false;
592
593                                 for (int i = 0; i < a.Count; ++i) {
594                                         if (!IsEqual (a.Types[i], b.Types[i]))
595                                                 return false;
596
597                                         const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
598                                         if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
599                                                 return false;
600                                 }
601
602                                 return true;
603                         }
604                 }
605
606                 //
607                 // Type variance equality comparison
608                 //
609                 public static class Variant
610                 {
611                         public static bool IsEqual (TypeSpec type1, TypeSpec type2)
612                         {
613                                 if (!type1.IsGeneric || !type2.IsGeneric)
614                                         return false;
615
616                                 var target_type_def = type2.MemberDefinition;
617                                 if (type1.MemberDefinition != target_type_def)
618                                         return false;
619
620                                 var t1_targs = type1.TypeArguments;
621                                 var t2_targs = type2.TypeArguments;
622                                 var targs_definition = target_type_def.TypeParameters;
623
624                                 if (!type1.IsInterface && !type1.IsDelegate) {
625                                         //
626                                         // Internal compiler variance between G<object> and G<dynamic>
627                                         //
628                                         for (int i = 0; i < targs_definition.Length; ++i) {
629                                                 if ((t1_targs[i] != TypeManager.object_type && t1_targs[i] != InternalType.Dynamic) ||
630                                                         (t2_targs[i] != TypeManager.object_type && t2_targs[i] != InternalType.Dynamic))
631                                                         return false;
632                                         }
633
634                                         return true;
635                                 }
636
637                                 for (int i = 0; i < targs_definition.Length; ++i) {
638                                         Variance v = targs_definition[i].Variance;
639                                         if (v == Variance.None) {
640                                                 if (t1_targs[i] == t2_targs[i])
641                                                         continue;
642                                                 return false;
643                                         }
644
645                                         if (v == Variance.Covariant) {
646                                                 if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
647                                                         return false;
648                                         } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
649                                                 return false;
650                                         }
651                                 }
652
653                                 return true;
654                         }
655                 }
656
657                 //
658                 // Checks whether two generic instances may become equal for some
659                 // particular instantiation (26.3.1).
660                 //
661                 public static class Unify
662                 {
663                         //
664                         // Either @a or @b must be generic type
665                         //
666                         public static bool IsEqual (TypeSpec a, TypeSpec b)
667                         {
668                                 if (a.MemberDefinition != b.MemberDefinition)
669                                         return false;
670
671                                 var ta = a.TypeArguments;
672                                 var tb = b.TypeArguments;
673                                 for (int i = 0; i < ta.Length; i++) {
674                                         if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
675                                                 return false;
676                                 }
677
678                                 return true;
679                         }
680
681                         static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
682                         {
683                                 TypeSpec[] targs = type.TypeArguments;
684                                 for (int i = 0; i < targs.Length; i++) {
685                                         if (tparam == targs[i])
686                                                 return true;
687
688                                         if (ContainsTypeParameter (tparam, targs[i]))
689                                                 return true;
690                                 }
691
692                                 return false;
693                         }
694
695                         /// <summary>
696                         ///   Check whether `a' and `b' may become equal generic types.
697                         ///   The algorithm to do that is a little bit complicated.
698                         /// </summary>
699                         static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
700                         {
701                                 if (a.IsGenericParameter) {
702                                         //
703                                         // If a is an array of a's type, they may never
704                                         // become equal.
705                                         //
706                                         if (b.IsArray)
707                                                 return false;
708
709                                         //
710                                         // If b is a generic parameter or an actual type,
711                                         // they may become equal:
712                                         //
713                                         //    class X<T,U> : I<T>, I<U>
714                                         //    class X<T> : I<T>, I<float>
715                                         // 
716                                         if (b.IsGenericParameter)
717                                                 return a.DeclaringType == b.DeclaringType;
718
719                                         //
720                                         // We're now comparing a type parameter with a
721                                         // generic instance.  They may become equal unless
722                                         // the type parameter appears anywhere in the
723                                         // generic instance:
724                                         //
725                                         //    class X<T,U> : I<T>, I<X<U>>
726                                         //        -> error because you could instanciate it as
727                                         //           X<X<int>,int>
728                                         //
729                                         //    class X<T> : I<T>, I<X<T>> -> ok
730                                         //
731
732                                         return !ContainsTypeParameter (a, b);
733                                 }
734
735                                 if (b.IsGenericParameter)
736                                         return MayBecomeEqualGenericTypes (b, a);
737
738                                 //
739                                 // At this point, neither a nor b are a type parameter.
740                                 //
741                                 // If one of them is a generic instance, compare them (if the
742                                 // other one is not a generic instance, they can never
743                                 // become equal).
744                                 //
745                                 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
746                                         return IsEqual (a, b);
747
748                                 //
749                                 // If both of them are arrays.
750                                 //
751                                 var a_ac = a as ArrayContainer;
752                                 if (a_ac != null) {
753                                         var b_ac = b as ArrayContainer;
754                                         if (b_ac == null || a_ac.Rank != b_ac.Rank)
755                                                 return false;
756
757                                         return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
758                                 }
759
760                                 //
761                                 // Ok, two ordinary types.
762                                 //
763                                 return false;
764                         }
765                 }
766         }
767
768         public interface ITypeDefinition : IMemberDefinition
769         {
770                 string Namespace { get; }
771                 int TypeParametersCount { get; }
772                 TypeParameterSpec[] TypeParameters { get; }
773
774                 TypeSpec GetAttributeCoClass ();
775                 string GetAttributeDefaultMember ();
776                 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
777                 MemberCache LoadMembers (TypeSpec declaringType);
778         }
779
780         class InternalType : TypeSpec
781         {
782                 private class DynamicType : InternalType
783                 {
784                         public DynamicType ()
785                                 : base ("dynamic")
786                         {
787                         }
788
789                         public override Type GetMetaInfo ()
790                         {
791                                 return typeof (object);
792                         }
793                 }
794
795                 public static readonly TypeSpec AnonymousMethod = new InternalType ("anonymous method");
796                 public static readonly TypeSpec Arglist = new InternalType ("__arglist");
797                 public static readonly TypeSpec Dynamic = new DynamicType ();
798                 public static readonly TypeSpec MethodGroup = new InternalType ("method group");
799                 public static readonly TypeSpec Null = new InternalType ("null");
800                 public static readonly TypeSpec FakeInternalType = new InternalType ("<fake$type>");
801
802                 readonly string name;
803
804                 protected InternalType (string name)
805                         : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
806                 {
807                         this.name = name;
808                         cache = MemberCache.Empty;
809
810                         // Make all internal types CLS-compliant, non-obsolete
811                         state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
812                 }
813
814                 public override int Arity {
815                         get {
816                                 return 0;
817                         }
818                 }
819
820                 public override string Name {
821                         get {
822                                 return name;
823                         }
824                 }
825
826                 public override string GetSignatureForError ()
827                 {
828                         return name;
829                 }
830         }
831
832         public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
833         {
834                 protected ElementTypeSpec (MemberKind kind, TypeSpec element, Type info)
835                         : base (kind, element.DeclaringType, null, info, element.Modifiers)
836                 {
837                         this.Element = element;
838
839                         // Has to use its own type definition instead of just element definition to
840                         // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
841                         this.definition = this;
842
843                         cache = MemberCache.Empty;
844                 }
845
846                 #region Properties
847
848                 public TypeSpec Element { get; private set; }
849
850                 public override string Name {
851                         get {
852                                 throw new NotSupportedException ();
853                         }
854                 }
855
856                 #endregion
857
858                 public override ObsoleteAttribute GetAttributeObsolete ()
859                 {
860                         return Element.GetAttributeObsolete ();
861                 }
862
863                 protected virtual string GetPostfixSignature ()
864                 {
865                         return null;
866                 }
867
868                 public override string GetSignatureForError ()
869                 {
870                         return Element.GetSignatureForError () + GetPostfixSignature ();
871                 }
872
873                 public override TypeSpec Mutate (TypeParameterMutator mutator)
874                 {
875                         var me = Element.Mutate (mutator);
876                         if (me == Element)
877                                 return this;
878
879                         var mutated = (ElementTypeSpec) MemberwiseClone ();
880                         mutated.Element = me;
881                         mutated.info = null;
882                         return mutated;
883                 }
884
885                 #region ITypeDefinition Members
886
887                 System.Reflection.Assembly IMemberDefinition.Assembly {
888                         get {
889                                 return Element.Assembly;
890                         }
891                 }
892
893                 public string Namespace {
894                         get { throw new NotImplementedException (); }
895                 }
896
897                 public int TypeParametersCount {
898                         get {
899                                 return 0;
900                         }
901                 }
902
903                 public TypeParameterSpec[] TypeParameters {
904                         get {
905                                 throw new NotSupportedException ();
906                         }
907                 }
908
909                 public TypeSpec GetAttributeCoClass ()
910                 {
911                         return Element.MemberDefinition.GetAttributeCoClass ();
912                 }
913
914                 public string GetAttributeDefaultMember ()
915                 {
916                         return Element.MemberDefinition.GetAttributeDefaultMember ();
917                 }
918
919                 public MemberCache LoadMembers (TypeSpec declaringType)
920                 {
921                         return Element.MemberDefinition.LoadMembers (declaringType);
922                 }
923
924                 public bool IsImported {
925                         get {
926                                 return Element.MemberDefinition.IsImported;
927                         }
928                 }
929
930                 public string[] ConditionalConditions ()
931                 {
932                         return Element.MemberDefinition.ConditionalConditions ();
933                 }
934
935                 bool IMemberDefinition.IsNotCLSCompliant ()
936                 {
937                         return Element.MemberDefinition.IsNotCLSCompliant ();
938                 }
939
940                 public void SetIsAssigned ()
941                 {
942                         Element.MemberDefinition.SetIsAssigned ();
943                 }
944
945                 public void SetIsUsed ()
946                 {
947                         Element.MemberDefinition.SetIsUsed ();
948                 }
949
950                 #endregion
951         }
952
953         public class ArrayContainer : ElementTypeSpec
954         {
955                 struct TypeRankPair : IEquatable<TypeRankPair>
956                 {
957                         TypeSpec ts;
958                         int rank;
959
960                         public TypeRankPair (TypeSpec ts, int rank)
961                         {
962                                 this.ts = ts;
963                                 this.rank = rank;
964                         }
965
966                         public override int GetHashCode ()
967                         {
968                                 return ts.GetHashCode () ^ rank.GetHashCode ();
969                         }
970
971                         #region IEquatable<Tuple<T1,T2>> Members
972
973                         public bool Equals (TypeRankPair other)
974                         {
975                                 return other.ts == ts && other.rank == rank;
976                         }
977
978                         #endregion
979                 }
980
981                 readonly int rank;
982                 static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
983
984                 private ArrayContainer (TypeSpec element, int rank)
985                         : base (MemberKind.ArrayType, element, null)
986                 {
987                         this.rank = rank;
988                 }
989
990                 public int Rank {
991                         get {
992                                 return rank;
993                         }
994                 }
995
996                 public System.Reflection.MethodInfo GetConstructor ()
997                 {
998                         var mb = RootContext.ToplevelTypes.Builder;
999
1000                         var arg_types = new Type[rank];
1001                         for (int i = 0; i < rank; i++)
1002                                 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1003
1004                         var ctor = mb.GetArrayMethod (
1005                                 GetMetaInfo (), ".ctor",
1006                                 System.Reflection.CallingConventions.HasThis,
1007                                 null, arg_types);
1008
1009                         return ctor;
1010                 }
1011
1012                 public System.Reflection.MethodInfo GetAddressMethod ()
1013                 {
1014                         var mb = RootContext.ToplevelTypes.Builder;
1015
1016                         var arg_types = new Type[rank];
1017                         for (int i = 0; i < rank; i++)
1018                                 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1019
1020                         var address = mb.GetArrayMethod (
1021                                 GetMetaInfo (), "Address",
1022                                 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1023                                 ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
1024
1025                         return address;
1026                 }
1027
1028                 public System.Reflection.MethodInfo GetGetMethod ()
1029                 {
1030                         var mb = RootContext.ToplevelTypes.Builder;
1031
1032                         var arg_types = new Type[rank];
1033                         for (int i = 0; i < rank; i++)
1034                                 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1035
1036                         var get = mb.GetArrayMethod (
1037                                 GetMetaInfo (), "Get",
1038                                 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1039                                 Element.GetMetaInfo (), arg_types);
1040
1041                         return get;
1042                 }
1043
1044                 public System.Reflection.MethodInfo GetSetMethod ()
1045                 {
1046                         var mb = RootContext.ToplevelTypes.Builder;
1047
1048                         var arg_types = new Type[rank + 1];
1049                         for (int i = 0; i < rank; i++)
1050                                 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1051
1052                         arg_types[rank] = Element.GetMetaInfo ();
1053
1054                         var set = mb.GetArrayMethod (
1055                                 GetMetaInfo (), "Set",
1056                                 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1057                                 TypeManager.void_type.GetMetaInfo (), arg_types);
1058
1059                         return set;
1060                 }
1061
1062                 public override Type GetMetaInfo ()
1063                 {
1064                         if (info == null) {
1065                                 if (rank == 1)
1066                                         info = Element.GetMetaInfo ().MakeArrayType ();
1067                                 else
1068                                         info = Element.GetMetaInfo ().MakeArrayType (rank);
1069                         }
1070
1071                         return info;
1072                 }
1073
1074                 protected override string GetPostfixSignature()
1075                 {
1076                         return GetPostfixSignature (rank);
1077                 }
1078
1079                 public static string GetPostfixSignature (int rank)
1080                 {
1081                         StringBuilder sb = new StringBuilder ();
1082                         sb.Append ("[");
1083                         for (int i = 1; i < rank; i++) {
1084                                 sb.Append (",");
1085                         }
1086                         sb.Append ("]");
1087
1088                         return sb.ToString ();
1089                 }
1090
1091                 public static ArrayContainer MakeType (TypeSpec element)
1092                 {
1093                         return MakeType (element, 1);
1094                 }
1095
1096                 public static ArrayContainer MakeType (TypeSpec element, int rank)
1097                 {
1098                         ArrayContainer ac;
1099                         var key = new TypeRankPair (element, rank);
1100                         if (!instances.TryGetValue (key, out ac)) {
1101                                 ac = new ArrayContainer (element, rank) {
1102                                         BaseType = TypeManager.array_type
1103                                 };
1104
1105                                 instances.Add (key, ac);
1106                         }
1107
1108                         return ac;
1109                 }
1110
1111                 public static void Reset ()
1112                 {
1113                         instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1114                 }
1115         }
1116
1117         class ReferenceContainer : ElementTypeSpec
1118         {
1119                 static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1120
1121                 private ReferenceContainer (TypeSpec element)
1122                         : base (MemberKind.Class, element, null)        // TODO: Kind.Class is most likely wrong
1123                 {
1124                 }
1125
1126                 public override Type GetMetaInfo ()
1127                 {
1128                         if (info == null) {
1129                                 info = Element.GetMetaInfo ().MakeByRefType ();
1130                         }
1131
1132                         return info;
1133                 }
1134
1135                 public static ReferenceContainer MakeType (TypeSpec element)
1136                 {
1137                         ReferenceContainer pc;
1138                         if (!instances.TryGetValue (element, out pc)) {
1139                                 pc = new ReferenceContainer (element);
1140                                 instances.Add (element, pc);
1141                         }
1142
1143                         return pc;
1144                 }
1145
1146                 public static void Reset ()
1147                 {
1148                         instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1149                 }
1150         }
1151
1152         class PointerContainer : ElementTypeSpec
1153         {
1154                 static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
1155
1156                 private PointerContainer (TypeSpec element)
1157                         : base (MemberKind.PointerType, element, null)
1158                 {
1159                         // It's never CLS-Compliant
1160                         state &= ~StateFlags.CLSCompliant_Undetected;
1161                 }
1162
1163                 public override Type GetMetaInfo ()
1164                 {
1165                         if (info == null) {
1166                                 info = Element.GetMetaInfo ().MakePointerType ();
1167                         }
1168
1169                         return info;
1170                 }
1171
1172                 protected override string GetPostfixSignature()
1173                 {
1174                         return "*";
1175                 }
1176
1177                 public static PointerContainer MakeType (TypeSpec element)
1178                 {
1179                         PointerContainer pc;
1180                         if (!instances.TryGetValue (element, out pc)) {
1181                                 pc = new PointerContainer (element);
1182                                 instances.Add (element, pc);
1183                         }
1184
1185                         return pc;
1186                 }
1187
1188                 public static void Reset ()
1189                 {
1190                         instances = new Dictionary<TypeSpec, PointerContainer> ();
1191                 }
1192         }
1193 }