2 // typespec.cs: Type specification
4 // Authors: Marek Safar (marek.safar@gmail.com)
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 // Copyright 2010 Novell, Inc
12 using System.Collections.Generic;
18 public class TypeSpec : MemberSpec
21 protected MemberCache cache;
22 protected IList<TypeSpec> ifaces;
25 Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
27 public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
29 // Reflection Emit hacking
30 static Type TypeBuilder;
31 static Type GenericTypeBuilder;
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");
42 public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, Type info, Modifiers modifiers)
43 : base (kind, declaringType, definition, modifiers)
45 this.declaringType = declaringType;
48 if (definition != null && definition.TypeParametersCount > 0)
49 state |= StateFlags.IsGeneric;
54 public override int Arity {
56 return MemberDefinition.TypeParametersCount;
60 public virtual TypeSpec BaseType {
69 public bool HasDynamicElement {
71 return (state & StateFlags.HasDynamicElement) != 0;
75 public virtual IList<TypeSpec> Interfaces {
86 return Kind == MemberKind.ArrayType;
90 public bool IsAttribute {
100 if (type == TypeManager.attribute_type)
103 type = type.base_type;
104 } while (type != null);
110 public bool IsInterface {
112 return Kind == MemberKind.Interface;
116 public bool IsClass {
118 return Kind == MemberKind.Class;
122 public bool IsConstantCompatible {
124 if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
127 return TypeManager.IsPrimitiveType (this) || this == TypeManager.decimal_type || this == InternalType.Dynamic;
131 public bool IsDelegate {
133 return Kind == MemberKind.Delegate;
138 get { return Kind == MemberKind.Enum; }
141 // TODO: Should probably do
142 // IsGenericType -- recursive
143 // HasTypeParameter -- non-recursive
144 public bool IsGenericOrParentIsGeneric {
150 ts = ts.declaringType;
151 } while (ts != null);
157 public bool IsGenericParameter {
158 get { return Kind == MemberKind.TypeParameter; }
161 public bool IsNested {
162 get { return declaringType != null && Kind != MemberKind.TypeParameter; }
165 public bool IsPointer {
167 return Kind == MemberKind.PointerType;
171 public bool IsSealed {
172 get { return (Modifiers & Modifiers.SEALED) != 0; }
175 public bool IsStruct {
177 return Kind == MemberKind.Struct;
181 public bool IsTypeBuilder {
183 var meta = GetMetaInfo().GetType ();
184 return meta == TypeBuilder || meta == GenericTypeBuilder;
188 public MemberCache MemberCache {
190 if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
191 InitializeMemberCache (false);
197 throw new InternalErrorException ("Membercache reset");
203 public MemberCache MemberCacheTypes {
206 InitializeMemberCache (true);
212 public new ITypeDefinition MemberDefinition {
214 return (ITypeDefinition) definition;
218 // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
219 // remove the property, YES IT WOULD !!!
220 public virtual TypeSpec[] TypeArguments {
221 get { return TypeSpec.EmptyTypes; }
226 public bool AddInterface (TypeSpec iface)
228 if ((state & StateFlags.InterfacesExpanded) != 0)
229 throw new InternalErrorException ("Modifying expanded interface list");
231 if (ifaces == null) {
232 ifaces = new List<TypeSpec> () { iface };
236 if (!ifaces.Contains (iface)) {
244 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
246 if (Kind != MemberKind.Class)
247 throw new InternalErrorException ();
250 return Attribute.DefaultUsageAttribute;
252 AttributeUsageAttribute aua = null;
254 while (type != null) {
255 aua = type.MemberDefinition.GetAttributeUsage (pa);
259 type = type.BaseType;
265 public virtual Type GetMetaInfo ()
270 public virtual TypeSpec GetDefinition ()
275 public override string GetSignatureForError ()
280 s = DeclaringType.GetSignatureForError ();
281 } else if (MemberDefinition is AnonymousTypeClass) {
282 return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
284 s = MemberDefinition.Namespace;
287 if (!string.IsNullOrEmpty (s))
290 return s + Name + GetTypeNameSignature ();
293 protected virtual string GetTypeNameSignature ()
298 return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
301 public bool ImplementsInterface (TypeSpec iface, bool variantly)
305 if (t.Interfaces != null) { // TODO: Try t.iface
306 foreach (TypeSpec i in t.Interfaces) {
307 if (i == iface || TypeSpecComparer.IsEqual (i, iface))
310 if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface))
321 protected virtual void InitializeMemberCache (bool onlyTypes)
323 MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
326 state |= StateFlags.PendingMemberCacheMembers;
328 state &= ~StateFlags.PendingMemberCacheMembers;
332 // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
333 // comparison is used to hide differences between `object' and `dynamic' for generic
334 // types. Should not be used for comparisons where G<object> != G<dynamic>
336 public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
338 if (dynamicIsObject && baseClass.IsGeneric) {
340 // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
342 // class B : A<object> {}
344 while (type != null) {
345 type = type.BaseType;
346 if (TypeSpecComparer.IsEqual (type, baseClass))
353 while (type != null) {
354 type = type.BaseType;
355 if (type == baseClass)
362 public override MemberSpec InflateMember (TypeParameterInflator inflator)
364 var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
367 // When inflating nested type from inside the type instance will be same
368 // because type parameters are same for all nested types
370 if (DeclaringType == inflator.TypeInstance)
371 return MakeGenericType (targs);
373 return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
376 public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
378 if (targs.Length == 0 && !IsNested)
379 throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
381 InflatedTypeSpec instance;
383 if (inflated_instances == null)
384 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
386 if (!inflated_instances.TryGetValue (targs, out instance)) {
387 if (GetDefinition () != this && !IsNested)
388 throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
389 GetSignatureForError ());
391 instance = new InflatedTypeSpec (this, declaringType, targs);
392 inflated_instances.Add (targs, instance);
398 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
403 public void SetMetaInfo (Type info)
405 if (this.info != null)
406 throw new InternalErrorException ("MetaInfo reset");
411 public void SetExtensionMethodContainer ()
413 modifiers |= Modifiers.METHOD_EXTENSION;
417 public class PredefinedTypeSpec : TypeSpec
422 public PredefinedTypeSpec (MemberKind kind, string ns, string name)
423 : base (kind, null, null, null, Modifiers.PUBLIC)
425 if (kind == MemberKind.Struct)
426 modifiers |= Modifiers.SEALED;
434 public override int Arity {
440 public override string Name {
446 public string Namespace {
454 public override string GetSignatureForError ()
457 case "Int32": return "int";
458 case "Int64": return "long";
459 case "String": return "string";
460 case "Boolean": return "bool";
461 case "Void": return "void";
462 case "Object": return "object";
463 case "UInt32": return "uint";
464 case "Int16": return "short";
465 case "UInt16": return "ushort";
466 case "UInt64": return "ulong";
467 case "Single": return "float";
468 case "Double": return "double";
469 case "Decimal": return "decimal";
470 case "Char": return "char";
471 case "Byte": return "byte";
472 case "SByte": return "sbyte";
475 return ns + "." + name;
478 public void SetDefinition (ITypeDefinition td, Type type)
480 this.definition = td;
484 public void SetDefinition (TypeSpec ts)
486 this.definition = ts.MemberDefinition;
487 this.info = ts.GetMetaInfo ();
488 this.BaseType = ts.BaseType;
489 this.Interfaces = ts.Interfaces;
493 static class TypeSpecComparer
496 // Does strict reference comparion only
498 public static readonly DefaultImpl Default = new DefaultImpl ();
500 public class DefaultImpl : IEqualityComparer<TypeSpec[]>
502 #region IEqualityComparer<TypeSpec[]> Members
504 bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
509 if (x.Length != y.Length)
512 for (int i = 0; i < x.Length; ++i)
519 int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
522 for (int i = 0; i < obj.Length; ++i)
523 hash = (hash << 5) - hash + obj[i].GetHashCode ();
532 // When comparing type signature of overrides or overloads
533 // this version tolerates different MVARs at same position
535 public static class Override
537 public static bool IsEqual (TypeSpec a, TypeSpec b)
543 // Consider the following example:
545 // public abstract class A
547 // public abstract T Foo<T>();
550 // public class B : A
552 // public override U Foo<T>() { return default (U); }
555 // Here, `T' and `U' are method type parameters from different methods
556 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
558 // However, since we're determining whether B.Foo() overrides A.Foo(),
559 // we need to do a signature based comparision and consider them equal.
562 var tp_a = a as TypeParameterSpec;
564 var tp_b = b as TypeParameterSpec;
565 return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
568 var ac_a = a as ArrayContainer;
570 var ac_b = b as ArrayContainer;
571 return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
574 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
575 return b == TypeManager.object_type || a == TypeManager.object_type;
577 if (a.MemberDefinition != b.MemberDefinition)
581 for (int i = 0; i < a.TypeArguments.Length; ++i) {
582 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
594 // Compares unordered arrays
596 public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
601 if (a == null || b == null || a.Length != b.Length)
604 for (int ai = 0; ai < a.Length; ++ai) {
606 for (int bi = 0; bi < b.Length; ++bi) {
607 if (IsEqual (a[ai], b[bi])) {
620 public static bool IsEqual (AParametersCollection a, AParametersCollection b)
625 if (a.Count != b.Count)
628 for (int i = 0; i < a.Count; ++i) {
629 if (!IsEqual (a.Types[i], b.Types[i]))
632 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
633 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
642 // Type variance equality comparison
644 public static class Variant
646 public static bool IsEqual (TypeSpec type1, TypeSpec type2)
648 if (!type1.IsGeneric || !type2.IsGeneric)
651 var target_type_def = type2.MemberDefinition;
652 if (type1.MemberDefinition != target_type_def)
655 var t1_targs = type1.TypeArguments;
656 var t2_targs = type2.TypeArguments;
657 var targs_definition = target_type_def.TypeParameters;
659 if (!type1.IsInterface && !type1.IsDelegate) {
663 for (int i = 0; i < targs_definition.Length; ++i) {
664 Variance v = targs_definition[i].Variance;
665 if (v == Variance.None) {
666 if (t1_targs[i] == t2_targs[i])
671 if (v == Variance.Covariant) {
672 if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
674 } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
684 // Checks whether two generic instances may become equal for some
685 // particular instantiation (26.3.1).
687 public static class Unify
690 // Either @a or @b must be generic type
692 public static bool IsEqual (TypeSpec a, TypeSpec b)
694 if (a.MemberDefinition != b.MemberDefinition)
697 var ta = a.TypeArguments;
698 var tb = b.TypeArguments;
699 for (int i = 0; i < ta.Length; i++) {
700 if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
707 static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
709 TypeSpec[] targs = type.TypeArguments;
710 for (int i = 0; i < targs.Length; i++) {
711 if (tparam == targs[i])
714 if (ContainsTypeParameter (tparam, targs[i]))
722 /// Check whether `a' and `b' may become equal generic types.
723 /// The algorithm to do that is a little bit complicated.
725 static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
727 if (a.IsGenericParameter) {
729 // If a is an array of a's type, they may never
736 // If b is a generic parameter or an actual type,
737 // they may become equal:
739 // class X<T,U> : I<T>, I<U>
740 // class X<T> : I<T>, I<float>
742 if (b.IsGenericParameter)
743 return a.DeclaringType == b.DeclaringType;
746 // We're now comparing a type parameter with a
747 // generic instance. They may become equal unless
748 // the type parameter appears anywhere in the
751 // class X<T,U> : I<T>, I<X<U>>
752 // -> error because you could instanciate it as
755 // class X<T> : I<T>, I<X<T>> -> ok
758 return !ContainsTypeParameter (a, b);
761 if (b.IsGenericParameter)
762 return MayBecomeEqualGenericTypes (b, a);
765 // At this point, neither a nor b are a type parameter.
767 // If one of them is a generic instance, compare them (if the
768 // other one is not a generic instance, they can never
771 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
772 return IsEqual (a, b);
775 // If both of them are arrays.
777 var a_ac = a as ArrayContainer;
779 var b_ac = b as ArrayContainer;
780 if (b_ac == null || a_ac.Rank != b_ac.Rank)
783 return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
787 // Ok, two ordinary types.
793 public static bool Equals (TypeSpec[] x, TypeSpec[] y)
798 if (x.Length != y.Length)
801 for (int i = 0; i < x.Length; ++i)
802 if (!IsEqual (x[i], y[i]))
809 // Identity type conversion
811 // Default reference comparison, it has to be used when comparing
812 // two possible dynamic/internal types
814 public static bool IsEqual (TypeSpec a, TypeSpec b)
817 // This also rejects dynamic == dynamic
818 return a.Kind != MemberKind.InternalCompilerType || a == InternalType.Dynamic;
822 // object and dynamic are considered equivalent there is an identity conversion
823 // between object and dynamic, and between constructed types that are the same
824 // when replacing all occurences of dynamic with object.
826 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
827 return b == TypeManager.object_type || a == TypeManager.object_type;
833 var a_a = (ArrayContainer) a;
834 var b_a = b as ArrayContainer;
838 return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank;
841 if (!a.IsGeneric || b == null || !b.IsGeneric)
844 if (a.MemberDefinition != b.MemberDefinition)
848 if (!Equals (a.TypeArguments, b.TypeArguments))
859 public interface ITypeDefinition : IMemberDefinition
861 string Namespace { get; }
862 int TypeParametersCount { get; }
863 TypeParameterSpec[] TypeParameters { get; }
865 TypeSpec GetAttributeCoClass ();
866 string GetAttributeDefaultMember ();
867 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
868 void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
871 class InternalType : TypeSpec, ITypeDefinition
873 public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
874 public static readonly InternalType Arglist = new InternalType ("__arglist");
875 public static readonly InternalType Dynamic = new InternalType ("dynamic", null);
876 public static readonly InternalType MethodGroup = new InternalType ("method group");
877 public static readonly InternalType Null = new InternalType ("null");
878 public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
880 readonly string name;
882 InternalType (string name, MemberCache cache)
888 InternalType (string name)
889 : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
892 this.definition = this;
893 cache = MemberCache.Empty;
895 // Make all internal types CLS-compliant, non-obsolete
896 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
901 public override int Arity {
907 System.Reflection.Assembly IMemberDefinition.Assembly {
909 throw new NotImplementedException ();
913 bool IMemberDefinition.IsImported {
919 public override string Name {
925 string ITypeDefinition.Namespace {
931 int ITypeDefinition.TypeParametersCount {
937 TypeParameterSpec[] ITypeDefinition.TypeParameters {
945 public override string GetSignatureForError ()
950 #region ITypeDefinition Members
952 TypeSpec ITypeDefinition.GetAttributeCoClass ()
957 string ITypeDefinition.GetAttributeDefaultMember ()
962 AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
967 void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
969 throw new NotImplementedException ();
972 string[] IMemberDefinition.ConditionalConditions ()
977 ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
982 bool IMemberDefinition.IsNotCLSCompliant ()
987 void IMemberDefinition.SetIsAssigned ()
991 void IMemberDefinition.SetIsUsed ()
998 public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1000 protected ElementTypeSpec (MemberKind kind, TypeSpec element, Type info)
1001 : base (kind, element.DeclaringType, null, info, element.Modifiers)
1003 this.Element = element;
1004 if (element == InternalType.Dynamic || element.HasDynamicElement)
1005 state |= StateFlags.HasDynamicElement;
1007 // Has to use its own type definition instead of just element definition to
1008 // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1009 this.definition = this;
1011 cache = MemberCache.Empty;
1016 public TypeSpec Element { get; private set; }
1018 public override string Name {
1020 throw new NotSupportedException ();
1026 public override ObsoleteAttribute GetAttributeObsolete ()
1028 return Element.GetAttributeObsolete ();
1031 protected virtual string GetPostfixSignature ()
1036 public override string GetSignatureForError ()
1038 return Element.GetSignatureForError () + GetPostfixSignature ();
1041 public override TypeSpec Mutate (TypeParameterMutator mutator)
1043 var me = Element.Mutate (mutator);
1047 var mutated = (ElementTypeSpec) MemberwiseClone ();
1048 mutated.Element = me;
1049 mutated.info = null;
1053 #region ITypeDefinition Members
1055 System.Reflection.Assembly IMemberDefinition.Assembly {
1057 return Element.Assembly;
1061 public string Namespace {
1062 get { throw new NotImplementedException (); }
1065 public int TypeParametersCount {
1071 public TypeParameterSpec[] TypeParameters {
1073 throw new NotSupportedException ();
1077 public TypeSpec GetAttributeCoClass ()
1079 return Element.MemberDefinition.GetAttributeCoClass ();
1082 public string GetAttributeDefaultMember ()
1084 return Element.MemberDefinition.GetAttributeDefaultMember ();
1087 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1089 Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1092 public bool IsImported {
1094 return Element.MemberDefinition.IsImported;
1098 public string[] ConditionalConditions ()
1100 return Element.MemberDefinition.ConditionalConditions ();
1103 bool IMemberDefinition.IsNotCLSCompliant ()
1105 return Element.MemberDefinition.IsNotCLSCompliant ();
1108 public void SetIsAssigned ()
1110 Element.MemberDefinition.SetIsAssigned ();
1113 public void SetIsUsed ()
1115 Element.MemberDefinition.SetIsUsed ();
1121 public class ArrayContainer : ElementTypeSpec
1123 struct TypeRankPair : IEquatable<TypeRankPair>
1128 public TypeRankPair (TypeSpec ts, int rank)
1134 public override int GetHashCode ()
1136 return ts.GetHashCode () ^ rank.GetHashCode ();
1139 #region IEquatable<Tuple<T1,T2>> Members
1141 public bool Equals (TypeRankPair other)
1143 return other.ts == ts && other.rank == rank;
1150 static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1152 private ArrayContainer (TypeSpec element, int rank)
1153 : base (MemberKind.ArrayType, element, null)
1164 public System.Reflection.MethodInfo GetConstructor ()
1166 var mb = RootContext.ToplevelTypes.Builder;
1168 var arg_types = new Type[rank];
1169 for (int i = 0; i < rank; i++)
1170 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1172 var ctor = mb.GetArrayMethod (
1173 GetMetaInfo (), ".ctor",
1174 System.Reflection.CallingConventions.HasThis,
1180 public System.Reflection.MethodInfo GetAddressMethod ()
1182 var mb = RootContext.ToplevelTypes.Builder;
1184 var arg_types = new Type[rank];
1185 for (int i = 0; i < rank; i++)
1186 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1188 var address = mb.GetArrayMethod (
1189 GetMetaInfo (), "Address",
1190 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1191 ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
1196 public System.Reflection.MethodInfo GetGetMethod ()
1198 var mb = RootContext.ToplevelTypes.Builder;
1200 var arg_types = new Type[rank];
1201 for (int i = 0; i < rank; i++)
1202 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1204 var get = mb.GetArrayMethod (
1205 GetMetaInfo (), "Get",
1206 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1207 Element.GetMetaInfo (), arg_types);
1212 public System.Reflection.MethodInfo GetSetMethod ()
1214 var mb = RootContext.ToplevelTypes.Builder;
1216 var arg_types = new Type[rank + 1];
1217 for (int i = 0; i < rank; i++)
1218 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1220 arg_types[rank] = Element.GetMetaInfo ();
1222 var set = mb.GetArrayMethod (
1223 GetMetaInfo (), "Set",
1224 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1225 TypeManager.void_type.GetMetaInfo (), arg_types);
1230 public override Type GetMetaInfo ()
1234 info = Element.GetMetaInfo ().MakeArrayType ();
1236 info = Element.GetMetaInfo ().MakeArrayType (rank);
1242 protected override string GetPostfixSignature()
1244 return GetPostfixSignature (rank);
1247 public static string GetPostfixSignature (int rank)
1249 StringBuilder sb = new StringBuilder ();
1251 for (int i = 1; i < rank; i++) {
1256 return sb.ToString ();
1259 public static ArrayContainer MakeType (TypeSpec element)
1261 return MakeType (element, 1);
1264 public static ArrayContainer MakeType (TypeSpec element, int rank)
1267 var key = new TypeRankPair (element, rank);
1268 if (!instances.TryGetValue (key, out ac)) {
1269 ac = new ArrayContainer (element, rank) {
1270 BaseType = TypeManager.array_type
1273 instances.Add (key, ac);
1279 public static void Reset ()
1281 instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1285 class ReferenceContainer : ElementTypeSpec
1287 static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1289 private ReferenceContainer (TypeSpec element)
1290 : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
1294 public override Type GetMetaInfo ()
1297 info = Element.GetMetaInfo ().MakeByRefType ();
1303 public static ReferenceContainer MakeType (TypeSpec element)
1305 ReferenceContainer pc;
1306 if (!instances.TryGetValue (element, out pc)) {
1307 pc = new ReferenceContainer (element);
1308 instances.Add (element, pc);
1314 public static void Reset ()
1316 instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1320 class PointerContainer : ElementTypeSpec
1322 static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
1324 private PointerContainer (TypeSpec element)
1325 : base (MemberKind.PointerType, element, null)
1327 // It's never CLS-Compliant
1328 state &= ~StateFlags.CLSCompliant_Undetected;
1331 public override Type GetMetaInfo ()
1334 info = Element.GetMetaInfo ().MakePointerType ();
1340 protected override string GetPostfixSignature()
1345 public static PointerContainer MakeType (TypeSpec element)
1347 PointerContainer pc;
1348 if (!instances.TryGetValue (element, out pc)) {
1349 pc = new PointerContainer (element);
1350 instances.Add (element, pc);
1356 public static void Reset ()
1358 instances = new Dictionary<TypeSpec, PointerContainer> ();