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 readonly Type TypeBuilder;
31 static readonly 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);
374 return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
377 public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
379 if (targs.Length == 0 && !IsNested)
380 throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
382 InflatedTypeSpec instance;
384 if (inflated_instances == null) {
385 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
388 instance = this as InflatedTypeSpec;
389 if (instance != null) {
391 // Nested types could be inflated on already inflated instances
392 // Caching this type ensured we are using same instance for
393 // inside/outside inflation using local type parameters
395 inflated_instances.Add (TypeArguments, instance);
400 if (!inflated_instances.TryGetValue (targs, out instance)) {
401 if (GetDefinition () != this && !IsNested)
402 throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
403 GetSignatureForError ());
405 instance = new InflatedTypeSpec (this, declaringType, targs);
406 inflated_instances.Add (targs, instance);
412 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
417 public void SetMetaInfo (Type info)
419 if (this.info != null)
420 throw new InternalErrorException ("MetaInfo reset");
425 public void SetExtensionMethodContainer ()
427 modifiers |= Modifiers.METHOD_EXTENSION;
431 public class PredefinedTypeSpec : TypeSpec
436 public PredefinedTypeSpec (MemberKind kind, string ns, string name)
437 : base (kind, null, null, null, Modifiers.PUBLIC)
439 if (kind == MemberKind.Struct)
440 modifiers |= Modifiers.SEALED;
448 public override int Arity {
454 public override string Name {
460 public string Namespace {
468 public override string GetSignatureForError ()
471 case "Int32": return "int";
472 case "Int64": return "long";
473 case "String": return "string";
474 case "Boolean": return "bool";
475 case "Void": return "void";
476 case "Object": return "object";
477 case "UInt32": return "uint";
478 case "Int16": return "short";
479 case "UInt16": return "ushort";
480 case "UInt64": return "ulong";
481 case "Single": return "float";
482 case "Double": return "double";
483 case "Decimal": return "decimal";
484 case "Char": return "char";
485 case "Byte": return "byte";
486 case "SByte": return "sbyte";
489 return ns + "." + name;
492 public void SetDefinition (ITypeDefinition td, Type type)
494 this.definition = td;
498 public void SetDefinition (TypeSpec ts)
500 this.definition = ts.MemberDefinition;
501 this.info = ts.GetMetaInfo ();
502 this.BaseType = ts.BaseType;
503 this.Interfaces = ts.Interfaces;
507 static class TypeSpecComparer
510 // Does strict reference comparion only
512 public static readonly DefaultImpl Default = new DefaultImpl ();
514 public class DefaultImpl : IEqualityComparer<TypeSpec[]>
516 #region IEqualityComparer<TypeSpec[]> Members
518 bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
523 if (x.Length != y.Length)
526 for (int i = 0; i < x.Length; ++i)
533 int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
536 for (int i = 0; i < obj.Length; ++i)
537 hash = (hash << 5) - hash + obj[i].GetHashCode ();
546 // When comparing type signature of overrides or overloads
547 // this version tolerates different MVARs at same position
549 public static class Override
551 public static bool IsEqual (TypeSpec a, TypeSpec b)
557 // Consider the following example:
559 // public abstract class A
561 // public abstract T Foo<T>();
564 // public class B : A
566 // public override U Foo<T>() { return default (U); }
569 // Here, `T' and `U' are method type parameters from different methods
570 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
572 // However, since we're determining whether B.Foo() overrides A.Foo(),
573 // we need to do a signature based comparision and consider them equal.
576 var tp_a = a as TypeParameterSpec;
578 var tp_b = b as TypeParameterSpec;
579 return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
582 var ac_a = a as ArrayContainer;
584 var ac_b = b as ArrayContainer;
585 return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
588 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
589 return b == TypeManager.object_type || a == TypeManager.object_type;
591 if (a.MemberDefinition != b.MemberDefinition)
595 for (int i = 0; i < a.TypeArguments.Length; ++i) {
596 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
608 // Compares unordered arrays
610 public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
615 if (a == null || b == null || a.Length != b.Length)
618 for (int ai = 0; ai < a.Length; ++ai) {
620 for (int bi = 0; bi < b.Length; ++bi) {
621 if (IsEqual (a[ai], b[bi])) {
634 public static bool IsEqual (AParametersCollection a, AParametersCollection b)
639 if (a.Count != b.Count)
642 for (int i = 0; i < a.Count; ++i) {
643 if (!IsEqual (a.Types[i], b.Types[i]))
646 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
647 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
656 // Type variance equality comparison
658 public static class Variant
660 public static bool IsEqual (TypeSpec type1, TypeSpec type2)
662 if (!type1.IsGeneric || !type2.IsGeneric)
665 var target_type_def = type2.MemberDefinition;
666 if (type1.MemberDefinition != target_type_def)
669 var t1_targs = type1.TypeArguments;
670 var t2_targs = type2.TypeArguments;
671 var targs_definition = target_type_def.TypeParameters;
673 if (!type1.IsInterface && !type1.IsDelegate) {
677 for (int i = 0; i < targs_definition.Length; ++i) {
678 Variance v = targs_definition[i].Variance;
679 if (v == Variance.None) {
680 if (t1_targs[i] == t2_targs[i])
685 if (v == Variance.Covariant) {
686 if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
688 } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
698 // Checks whether two generic instances may become equal for some
699 // particular instantiation (26.3.1).
701 public static class Unify
704 // Either @a or @b must be generic type
706 public static bool IsEqual (TypeSpec a, TypeSpec b)
708 if (a.MemberDefinition != b.MemberDefinition)
711 var ta = a.TypeArguments;
712 var tb = b.TypeArguments;
713 for (int i = 0; i < ta.Length; i++) {
714 if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
721 static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
723 TypeSpec[] targs = type.TypeArguments;
724 for (int i = 0; i < targs.Length; i++) {
725 if (tparam == targs[i])
728 if (ContainsTypeParameter (tparam, targs[i]))
736 /// Check whether `a' and `b' may become equal generic types.
737 /// The algorithm to do that is a little bit complicated.
739 static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
741 if (a.IsGenericParameter) {
743 // If a is an array of a's type, they may never
750 // If b is a generic parameter or an actual type,
751 // they may become equal:
753 // class X<T,U> : I<T>, I<U>
754 // class X<T> : I<T>, I<float>
756 if (b.IsGenericParameter)
757 return a.DeclaringType == b.DeclaringType;
760 // We're now comparing a type parameter with a
761 // generic instance. They may become equal unless
762 // the type parameter appears anywhere in the
765 // class X<T,U> : I<T>, I<X<U>>
766 // -> error because you could instanciate it as
769 // class X<T> : I<T>, I<X<T>> -> ok
772 return !ContainsTypeParameter (a, b);
775 if (b.IsGenericParameter)
776 return MayBecomeEqualGenericTypes (b, a);
779 // At this point, neither a nor b are a type parameter.
781 // If one of them is a generic instance, compare them (if the
782 // other one is not a generic instance, they can never
785 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
786 return IsEqual (a, b);
789 // If both of them are arrays.
791 var a_ac = a as ArrayContainer;
793 var b_ac = b as ArrayContainer;
794 if (b_ac == null || a_ac.Rank != b_ac.Rank)
797 return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
801 // Ok, two ordinary types.
807 public static bool Equals (TypeSpec[] x, TypeSpec[] y)
812 if (x.Length != y.Length)
815 for (int i = 0; i < x.Length; ++i)
816 if (!IsEqual (x[i], y[i]))
823 // Identity type conversion
825 // Default reference comparison, it has to be used when comparing
826 // two possible dynamic/internal types
828 public static bool IsEqual (TypeSpec a, TypeSpec b)
831 // This also rejects dynamic == dynamic
832 return a.Kind != MemberKind.InternalCompilerType || a == InternalType.Dynamic;
836 // object and dynamic are considered equivalent there is an identity conversion
837 // between object and dynamic, and between constructed types that are the same
838 // when replacing all occurences of dynamic with object.
840 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
841 return b == TypeManager.object_type || a == TypeManager.object_type;
847 var a_a = (ArrayContainer) a;
848 var b_a = b as ArrayContainer;
852 return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank;
855 if (!a.IsGeneric || b == null || !b.IsGeneric)
858 if (a.MemberDefinition != b.MemberDefinition)
862 if (!Equals (a.TypeArguments, b.TypeArguments))
873 public interface ITypeDefinition : IMemberDefinition
875 string Namespace { get; }
876 int TypeParametersCount { get; }
877 TypeParameterSpec[] TypeParameters { get; }
879 TypeSpec GetAttributeCoClass ();
880 string GetAttributeDefaultMember ();
881 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
882 void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
885 class InternalType : TypeSpec, ITypeDefinition
887 public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
888 public static readonly InternalType Arglist = new InternalType ("__arglist");
889 public static readonly InternalType Dynamic = new InternalType ("dynamic", null);
890 public static readonly InternalType MethodGroup = new InternalType ("method group");
891 public static readonly InternalType Null = new InternalType ("null");
892 public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
894 readonly string name;
896 InternalType (string name, MemberCache cache)
902 InternalType (string name)
903 : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
906 this.definition = this;
907 cache = MemberCache.Empty;
909 // Make all internal types CLS-compliant, non-obsolete
910 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
915 public override int Arity {
921 System.Reflection.Assembly IMemberDefinition.Assembly {
923 throw new NotImplementedException ();
927 bool IMemberDefinition.IsImported {
933 public override string Name {
939 string ITypeDefinition.Namespace {
945 int ITypeDefinition.TypeParametersCount {
951 TypeParameterSpec[] ITypeDefinition.TypeParameters {
959 public override string GetSignatureForError ()
964 #region ITypeDefinition Members
966 TypeSpec ITypeDefinition.GetAttributeCoClass ()
971 string ITypeDefinition.GetAttributeDefaultMember ()
976 AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
981 void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
983 throw new NotImplementedException ();
986 string[] IMemberDefinition.ConditionalConditions ()
991 ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
996 bool IMemberDefinition.IsNotCLSCompliant ()
1001 void IMemberDefinition.SetIsAssigned ()
1005 void IMemberDefinition.SetIsUsed ()
1012 public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1014 protected ElementTypeSpec (MemberKind kind, TypeSpec element, Type info)
1015 : base (kind, element.DeclaringType, null, info, element.Modifiers)
1017 this.Element = element;
1018 if (element == InternalType.Dynamic || element.HasDynamicElement)
1019 state |= StateFlags.HasDynamicElement;
1021 // Has to use its own type definition instead of just element definition to
1022 // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1023 this.definition = this;
1025 cache = MemberCache.Empty;
1030 public TypeSpec Element { get; private set; }
1032 public override string Name {
1034 throw new NotSupportedException ();
1040 public override ObsoleteAttribute GetAttributeObsolete ()
1042 return Element.GetAttributeObsolete ();
1045 protected virtual string GetPostfixSignature ()
1050 public override string GetSignatureForError ()
1052 return Element.GetSignatureForError () + GetPostfixSignature ();
1055 public override TypeSpec Mutate (TypeParameterMutator mutator)
1057 var me = Element.Mutate (mutator);
1061 var mutated = (ElementTypeSpec) MemberwiseClone ();
1062 mutated.Element = me;
1063 mutated.info = null;
1067 #region ITypeDefinition Members
1069 System.Reflection.Assembly IMemberDefinition.Assembly {
1071 return Element.Assembly;
1075 public string Namespace {
1076 get { throw new NotImplementedException (); }
1079 public int TypeParametersCount {
1085 public TypeParameterSpec[] TypeParameters {
1087 throw new NotSupportedException ();
1091 public TypeSpec GetAttributeCoClass ()
1093 return Element.MemberDefinition.GetAttributeCoClass ();
1096 public string GetAttributeDefaultMember ()
1098 return Element.MemberDefinition.GetAttributeDefaultMember ();
1101 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1103 Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1106 public bool IsImported {
1108 return Element.MemberDefinition.IsImported;
1112 public string[] ConditionalConditions ()
1114 return Element.MemberDefinition.ConditionalConditions ();
1117 bool IMemberDefinition.IsNotCLSCompliant ()
1119 return Element.MemberDefinition.IsNotCLSCompliant ();
1122 public void SetIsAssigned ()
1124 Element.MemberDefinition.SetIsAssigned ();
1127 public void SetIsUsed ()
1129 Element.MemberDefinition.SetIsUsed ();
1135 public class ArrayContainer : ElementTypeSpec
1137 struct TypeRankPair : IEquatable<TypeRankPair>
1142 public TypeRankPair (TypeSpec ts, int rank)
1148 public override int GetHashCode ()
1150 return ts.GetHashCode () ^ rank.GetHashCode ();
1153 #region IEquatable<Tuple<T1,T2>> Members
1155 public bool Equals (TypeRankPair other)
1157 return other.ts == ts && other.rank == rank;
1164 static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1166 private ArrayContainer (TypeSpec element, int rank)
1167 : base (MemberKind.ArrayType, element, null)
1178 public System.Reflection.MethodInfo GetConstructor ()
1180 var mb = RootContext.ToplevelTypes.Builder;
1182 var arg_types = new Type[rank];
1183 for (int i = 0; i < rank; i++)
1184 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1186 var ctor = mb.GetArrayMethod (
1187 GetMetaInfo (), ".ctor",
1188 System.Reflection.CallingConventions.HasThis,
1194 public System.Reflection.MethodInfo GetAddressMethod ()
1196 var mb = RootContext.ToplevelTypes.Builder;
1198 var arg_types = new Type[rank];
1199 for (int i = 0; i < rank; i++)
1200 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1202 var address = mb.GetArrayMethod (
1203 GetMetaInfo (), "Address",
1204 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1205 ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
1210 public System.Reflection.MethodInfo GetGetMethod ()
1212 var mb = RootContext.ToplevelTypes.Builder;
1214 var arg_types = new Type[rank];
1215 for (int i = 0; i < rank; i++)
1216 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1218 var get = mb.GetArrayMethod (
1219 GetMetaInfo (), "Get",
1220 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1221 Element.GetMetaInfo (), arg_types);
1226 public System.Reflection.MethodInfo GetSetMethod ()
1228 var mb = RootContext.ToplevelTypes.Builder;
1230 var arg_types = new Type[rank + 1];
1231 for (int i = 0; i < rank; i++)
1232 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1234 arg_types[rank] = Element.GetMetaInfo ();
1236 var set = mb.GetArrayMethod (
1237 GetMetaInfo (), "Set",
1238 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1239 TypeManager.void_type.GetMetaInfo (), arg_types);
1244 public override Type GetMetaInfo ()
1248 info = Element.GetMetaInfo ().MakeArrayType ();
1250 info = Element.GetMetaInfo ().MakeArrayType (rank);
1256 protected override string GetPostfixSignature()
1258 return GetPostfixSignature (rank);
1261 public static string GetPostfixSignature (int rank)
1263 StringBuilder sb = new StringBuilder ();
1265 for (int i = 1; i < rank; i++) {
1270 return sb.ToString ();
1273 public static ArrayContainer MakeType (TypeSpec element)
1275 return MakeType (element, 1);
1278 public static ArrayContainer MakeType (TypeSpec element, int rank)
1281 var key = new TypeRankPair (element, rank);
1282 if (!instances.TryGetValue (key, out ac)) {
1283 ac = new ArrayContainer (element, rank) {
1284 BaseType = TypeManager.array_type
1287 instances.Add (key, ac);
1293 public static void Reset ()
1295 instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1299 class ReferenceContainer : ElementTypeSpec
1301 static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1303 private ReferenceContainer (TypeSpec element)
1304 : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
1308 public override Type GetMetaInfo ()
1311 info = Element.GetMetaInfo ().MakeByRefType ();
1317 public static ReferenceContainer MakeType (TypeSpec element)
1319 ReferenceContainer pc;
1320 if (!instances.TryGetValue (element, out pc)) {
1321 pc = new ReferenceContainer (element);
1322 instances.Add (element, pc);
1328 public static void Reset ()
1330 instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1334 class PointerContainer : ElementTypeSpec
1336 static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
1338 private PointerContainer (TypeSpec element)
1339 : base (MemberKind.PointerType, element, null)
1341 // It's never CLS-Compliant
1342 state &= ~StateFlags.CLSCompliant_Undetected;
1345 public override Type GetMetaInfo ()
1348 info = Element.GetMetaInfo ().MakePointerType ();
1354 protected override string GetPostfixSignature()
1359 public static PointerContainer MakeType (TypeSpec element)
1361 PointerContainer pc;
1362 if (!instances.TryGetValue (element, out pc)) {
1363 pc = new PointerContainer (element);
1364 instances.Add (element, pc);
1370 public static void Reset ()
1372 instances = new Dictionary<TypeSpec, PointerContainer> ();