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 virtual IList<TypeSpec> Interfaces {
80 return Kind == MemberKind.ArrayType;
84 public bool IsAttribute {
94 if (type == TypeManager.attribute_type)
97 type = type.base_type;
98 } while (type != null);
104 public bool IsInterface {
106 return Kind == MemberKind.Interface;
110 public bool IsClass {
112 return Kind == MemberKind.Class;
116 public bool IsConstantCompatible {
118 if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
121 return TypeManager.IsPrimitiveType (this) || this == TypeManager.decimal_type || this == InternalType.Dynamic;
125 public bool IsDelegate {
127 return Kind == MemberKind.Delegate;
132 get { return Kind == MemberKind.Enum; }
135 // TODO: Should probably do
136 // IsGenericType -- recursive
137 // HasTypeParameter -- non-recursive
138 public bool IsGenericOrParentIsGeneric {
144 ts = ts.declaringType;
145 } while (ts != null);
151 public bool IsGenericParameter {
152 get { return Kind == MemberKind.TypeParameter; }
155 public bool IsNested {
156 get { return declaringType != null && Kind != MemberKind.TypeParameter; }
159 public bool IsPointer {
161 return Kind == MemberKind.PointerType;
165 public bool IsSealed {
166 get { return (Modifiers & Modifiers.SEALED) != 0; }
169 public bool IsStruct {
171 return Kind == MemberKind.Struct;
175 public bool IsTypeBuilder {
177 var meta = GetMetaInfo().GetType ();
178 return meta == TypeBuilder || meta == GenericTypeBuilder;
182 public MemberCache MemberCache {
184 if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
185 InitializeMemberCache (false);
191 throw new InternalErrorException ("Membercache reset");
197 public MemberCache MemberCacheTypes {
200 InitializeMemberCache (true);
206 public new ITypeDefinition MemberDefinition {
208 return (ITypeDefinition) definition;
212 // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
213 // remove the property, YES IT WOULD !!!
214 public virtual TypeSpec[] TypeArguments {
215 get { return TypeSpec.EmptyTypes; }
220 public bool AddInterface (TypeSpec iface)
222 if ((state & StateFlags.InterfacesExpanded) != 0)
223 throw new InternalErrorException ("Modifying expanded interface list");
225 if (ifaces == null) {
226 ifaces = new List<TypeSpec> () { iface };
230 if (!ifaces.Contains (iface)) {
238 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
240 if (Kind != MemberKind.Class)
241 throw new InternalErrorException ();
244 return Attribute.DefaultUsageAttribute;
246 AttributeUsageAttribute aua = null;
248 while (type != null) {
249 aua = type.MemberDefinition.GetAttributeUsage (pa);
253 type = type.BaseType;
259 public virtual Type GetMetaInfo ()
264 public virtual TypeSpec GetDefinition ()
269 public override string GetSignatureForError ()
274 s = DeclaringType.GetSignatureForError ();
275 } else if (MemberDefinition is AnonymousTypeClass) {
276 return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
278 s = MemberDefinition.Namespace;
281 if (!string.IsNullOrEmpty (s))
284 return s + Name + GetTypeNameSignature ();
287 protected virtual string GetTypeNameSignature ()
292 return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
295 public bool ImplementsInterface (TypeSpec iface, bool variantly)
299 if (t.Interfaces != null) { // TODO: Try t.iface
300 foreach (TypeSpec i in t.Interfaces) {
301 if (i == iface || TypeSpecComparer.IsEqual (i, iface))
304 if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface))
315 protected virtual void InitializeMemberCache (bool onlyTypes)
317 MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
320 state |= StateFlags.PendingMemberCacheMembers;
322 state &= ~StateFlags.PendingMemberCacheMembers;
326 // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
327 // comparison is used to hide differences between `object' and `dynamic' for generic
328 // types. Should not be used for comparisons where G<object> != G<dynamic>
330 public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
332 if (dynamicIsObject && baseClass.IsGeneric) {
334 // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
336 // class B : A<object> {}
338 while (type != null) {
339 type = type.BaseType;
340 if (TypeSpecComparer.IsEqual (type, baseClass))
347 while (type != null) {
348 type = type.BaseType;
349 if (type == baseClass)
356 public override MemberSpec InflateMember (TypeParameterInflator inflator)
358 var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
361 // When inflating nested type from inside the type instance will be same
362 // because type parameters are same for all nested types
364 if (DeclaringType == inflator.TypeInstance)
365 return MakeGenericType (targs);
367 return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
370 public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
372 if (targs.Length == 0 && !IsNested)
373 throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
375 InflatedTypeSpec instance;
377 if (inflated_instances == null)
378 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
380 if (!inflated_instances.TryGetValue (targs, out instance)) {
381 if (GetDefinition () != this && !IsNested)
382 throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
383 GetSignatureForError ());
385 instance = new InflatedTypeSpec (this, declaringType, targs);
386 inflated_instances.Add (targs, instance);
392 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
397 public void SetMetaInfo (Type info)
399 if (this.info != null)
400 throw new InternalErrorException ("MetaInfo reset");
405 public void SetExtensionMethodContainer ()
407 modifiers |= Modifiers.METHOD_EXTENSION;
411 public class PredefinedTypeSpec : TypeSpec
416 public PredefinedTypeSpec (MemberKind kind, string ns, string name)
417 : base (kind, null, null, null, Modifiers.PUBLIC)
425 public override int Arity {
431 public override string Name {
437 public string Namespace {
445 public override string GetSignatureForError ()
448 case "Int32": return "int";
449 case "Int64": return "long";
450 case "String": return "string";
451 case "Boolean": return "bool";
452 case "Void": return "void";
453 case "Object": return "object";
454 case "UInt32": return "uint";
455 case "Int16": return "short";
456 case "UInt16": return "ushort";
457 case "UInt64": return "ulong";
458 case "Single": return "float";
459 case "Double": return "double";
460 case "Decimal": return "decimal";
461 case "Char": return "char";
462 case "Byte": return "byte";
463 case "SByte": return "sbyte";
466 return ns + "." + name;
469 public void SetDefinition (ITypeDefinition td, Type type)
471 this.definition = td;
475 public void SetDefinition (TypeSpec ts)
477 this.definition = ts.MemberDefinition;
478 this.info = ts.GetMetaInfo ();
479 this.BaseType = ts.BaseType;
480 this.Interfaces = ts.Interfaces;
484 static class TypeSpecComparer
487 // Does strict reference comparion only
489 public static readonly DefaultImpl Default = new DefaultImpl ();
491 public class DefaultImpl : IEqualityComparer<TypeSpec[]>
493 #region IEqualityComparer<TypeSpec[]> Members
495 bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
500 if (x.Length != y.Length)
503 for (int i = 0; i < x.Length; ++i)
510 int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
513 for (int i = 0; i < obj.Length; ++i)
514 hash = (hash << 5) - hash + obj[i].GetHashCode ();
523 // When comparing type signature of overrides or overloads
524 // this version tolerates different MVARs at same position
526 public static class Override
528 public static bool IsEqual (TypeSpec a, TypeSpec b)
534 // Consider the following example:
536 // public abstract class A
538 // public abstract T Foo<T>();
541 // public class B : A
543 // public override U Foo<T>() { return default (U); }
546 // Here, `T' and `U' are method type parameters from different methods
547 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
549 // However, since we're determining whether B.Foo() overrides A.Foo(),
550 // we need to do a signature based comparision and consider them equal.
553 var tp_a = a as TypeParameterSpec;
555 var tp_b = b as TypeParameterSpec;
556 return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
559 if (a.TypeArguments.Length != b.TypeArguments.Length)
562 if (a.TypeArguments.Length != 0) {
563 if (a.MemberDefinition != b.MemberDefinition)
566 for (int i = 0; i < a.TypeArguments.Length; ++i) {
567 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
574 var ac_a = a as ArrayContainer;
576 var ac_b = b as ArrayContainer;
577 return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
580 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
581 return b == TypeManager.object_type || a == TypeManager.object_type;
587 // Compares unordered arrays
589 public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
594 if (a == null || b == null || a.Length != b.Length)
597 for (int ai = 0; ai < a.Length; ++ai) {
599 for (int bi = 0; bi < b.Length; ++bi) {
600 if (IsEqual (a[ai], b[bi])) {
613 public static bool IsEqual (AParametersCollection a, AParametersCollection b)
618 if (a.Count != b.Count)
621 for (int i = 0; i < a.Count; ++i) {
622 if (!IsEqual (a.Types[i], b.Types[i]))
625 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
626 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
635 // Type variance equality comparison
637 public static class Variant
639 public static bool IsEqual (TypeSpec type1, TypeSpec type2)
641 if (!type1.IsGeneric || !type2.IsGeneric)
644 var target_type_def = type2.MemberDefinition;
645 if (type1.MemberDefinition != target_type_def)
648 var t1_targs = type1.TypeArguments;
649 var t2_targs = type2.TypeArguments;
650 var targs_definition = target_type_def.TypeParameters;
652 if (!type1.IsInterface && !type1.IsDelegate) {
656 for (int i = 0; i < targs_definition.Length; ++i) {
657 Variance v = targs_definition[i].Variance;
658 if (v == Variance.None) {
659 if (t1_targs[i] == t2_targs[i])
664 if (v == Variance.Covariant) {
665 if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
667 } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
677 // Checks whether two generic instances may become equal for some
678 // particular instantiation (26.3.1).
680 public static class Unify
683 // Either @a or @b must be generic type
685 public static bool IsEqual (TypeSpec a, TypeSpec b)
687 if (a.MemberDefinition != b.MemberDefinition)
690 var ta = a.TypeArguments;
691 var tb = b.TypeArguments;
692 for (int i = 0; i < ta.Length; i++) {
693 if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
700 static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
702 TypeSpec[] targs = type.TypeArguments;
703 for (int i = 0; i < targs.Length; i++) {
704 if (tparam == targs[i])
707 if (ContainsTypeParameter (tparam, targs[i]))
715 /// Check whether `a' and `b' may become equal generic types.
716 /// The algorithm to do that is a little bit complicated.
718 static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
720 if (a.IsGenericParameter) {
722 // If a is an array of a's type, they may never
729 // If b is a generic parameter or an actual type,
730 // they may become equal:
732 // class X<T,U> : I<T>, I<U>
733 // class X<T> : I<T>, I<float>
735 if (b.IsGenericParameter)
736 return a.DeclaringType == b.DeclaringType;
739 // We're now comparing a type parameter with a
740 // generic instance. They may become equal unless
741 // the type parameter appears anywhere in the
744 // class X<T,U> : I<T>, I<X<U>>
745 // -> error because you could instanciate it as
748 // class X<T> : I<T>, I<X<T>> -> ok
751 return !ContainsTypeParameter (a, b);
754 if (b.IsGenericParameter)
755 return MayBecomeEqualGenericTypes (b, a);
758 // At this point, neither a nor b are a type parameter.
760 // If one of them is a generic instance, compare them (if the
761 // other one is not a generic instance, they can never
764 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
765 return IsEqual (a, b);
768 // If both of them are arrays.
770 var a_ac = a as ArrayContainer;
772 var b_ac = b as ArrayContainer;
773 if (b_ac == null || a_ac.Rank != b_ac.Rank)
776 return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
780 // Ok, two ordinary types.
786 public static bool Equals (TypeSpec[] x, TypeSpec[] y)
791 if (x.Length != y.Length)
794 for (int i = 0; i < x.Length; ++i)
795 if (!IsEqual (x[i], y[i]))
802 // Identity type conversion
804 // Default reference comparison, it has to be used when comparing
805 // two possible dynamic/internal types
807 public static bool IsEqual (TypeSpec a, TypeSpec b)
810 // This also rejects dynamic == dynamic
811 return a.Kind != MemberKind.InternalCompilerType || a == InternalType.Dynamic;
815 // object and dynamic are considered equivalent there is an identity conversion
816 // between object and dynamic, and between constructed types that are the same
817 // when replacing all occurences of dynamic with object.
819 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
820 return b == TypeManager.object_type || a == TypeManager.object_type;
826 var a_a = (ArrayContainer) a;
827 var b_a = b as ArrayContainer;
831 return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank;
834 if (!a.IsGeneric || b == null || !b.IsGeneric)
837 if (a.MemberDefinition != b.MemberDefinition)
841 if (!Equals (a.TypeArguments, b.TypeArguments))
852 public interface ITypeDefinition : IMemberDefinition
854 string Namespace { get; }
855 int TypeParametersCount { get; }
856 TypeParameterSpec[] TypeParameters { get; }
858 TypeSpec GetAttributeCoClass ();
859 string GetAttributeDefaultMember ();
860 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
861 void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
864 class InternalType : TypeSpec
866 public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
867 public static readonly InternalType Arglist = new InternalType ("__arglist");
868 public static readonly InternalType Dynamic = new InternalType ("dynamic", null);
869 public static readonly InternalType MethodGroup = new InternalType ("method group");
870 public static readonly InternalType Null = new InternalType ("null");
871 public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
873 readonly string name;
875 InternalType (string name, MemberCache cache)
881 InternalType (string name)
882 : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
885 cache = MemberCache.Empty;
887 // Make all internal types CLS-compliant, non-obsolete
888 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
893 public override int Arity {
899 public override string Name {
907 public override string GetSignatureForError ()
913 public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
915 protected ElementTypeSpec (MemberKind kind, TypeSpec element, Type info)
916 : base (kind, element.DeclaringType, null, info, element.Modifiers)
918 this.Element = element;
920 // Has to use its own type definition instead of just element definition to
921 // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
922 this.definition = this;
924 cache = MemberCache.Empty;
929 public TypeSpec Element { get; private set; }
931 public override string Name {
933 throw new NotSupportedException ();
939 public override ObsoleteAttribute GetAttributeObsolete ()
941 return Element.GetAttributeObsolete ();
944 protected virtual string GetPostfixSignature ()
949 public override string GetSignatureForError ()
951 return Element.GetSignatureForError () + GetPostfixSignature ();
954 public override TypeSpec Mutate (TypeParameterMutator mutator)
956 var me = Element.Mutate (mutator);
960 var mutated = (ElementTypeSpec) MemberwiseClone ();
961 mutated.Element = me;
966 #region ITypeDefinition Members
968 System.Reflection.Assembly IMemberDefinition.Assembly {
970 return Element.Assembly;
974 public string Namespace {
975 get { throw new NotImplementedException (); }
978 public int TypeParametersCount {
984 public TypeParameterSpec[] TypeParameters {
986 throw new NotSupportedException ();
990 public TypeSpec GetAttributeCoClass ()
992 return Element.MemberDefinition.GetAttributeCoClass ();
995 public string GetAttributeDefaultMember ()
997 return Element.MemberDefinition.GetAttributeDefaultMember ();
1000 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1002 Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1005 public bool IsImported {
1007 return Element.MemberDefinition.IsImported;
1011 public string[] ConditionalConditions ()
1013 return Element.MemberDefinition.ConditionalConditions ();
1016 bool IMemberDefinition.IsNotCLSCompliant ()
1018 return Element.MemberDefinition.IsNotCLSCompliant ();
1021 public void SetIsAssigned ()
1023 Element.MemberDefinition.SetIsAssigned ();
1026 public void SetIsUsed ()
1028 Element.MemberDefinition.SetIsUsed ();
1034 public class ArrayContainer : ElementTypeSpec
1036 struct TypeRankPair : IEquatable<TypeRankPair>
1041 public TypeRankPair (TypeSpec ts, int rank)
1047 public override int GetHashCode ()
1049 return ts.GetHashCode () ^ rank.GetHashCode ();
1052 #region IEquatable<Tuple<T1,T2>> Members
1054 public bool Equals (TypeRankPair other)
1056 return other.ts == ts && other.rank == rank;
1063 static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1065 private ArrayContainer (TypeSpec element, int rank)
1066 : base (MemberKind.ArrayType, element, null)
1077 public System.Reflection.MethodInfo GetConstructor ()
1079 var mb = RootContext.ToplevelTypes.Builder;
1081 var arg_types = new Type[rank];
1082 for (int i = 0; i < rank; i++)
1083 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1085 var ctor = mb.GetArrayMethod (
1086 GetMetaInfo (), ".ctor",
1087 System.Reflection.CallingConventions.HasThis,
1093 public System.Reflection.MethodInfo GetAddressMethod ()
1095 var mb = RootContext.ToplevelTypes.Builder;
1097 var arg_types = new Type[rank];
1098 for (int i = 0; i < rank; i++)
1099 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1101 var address = mb.GetArrayMethod (
1102 GetMetaInfo (), "Address",
1103 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1104 ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
1109 public System.Reflection.MethodInfo GetGetMethod ()
1111 var mb = RootContext.ToplevelTypes.Builder;
1113 var arg_types = new Type[rank];
1114 for (int i = 0; i < rank; i++)
1115 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1117 var get = mb.GetArrayMethod (
1118 GetMetaInfo (), "Get",
1119 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1120 Element.GetMetaInfo (), arg_types);
1125 public System.Reflection.MethodInfo GetSetMethod ()
1127 var mb = RootContext.ToplevelTypes.Builder;
1129 var arg_types = new Type[rank + 1];
1130 for (int i = 0; i < rank; i++)
1131 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1133 arg_types[rank] = Element.GetMetaInfo ();
1135 var set = mb.GetArrayMethod (
1136 GetMetaInfo (), "Set",
1137 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1138 TypeManager.void_type.GetMetaInfo (), arg_types);
1143 public override Type GetMetaInfo ()
1147 info = Element.GetMetaInfo ().MakeArrayType ();
1149 info = Element.GetMetaInfo ().MakeArrayType (rank);
1155 protected override string GetPostfixSignature()
1157 return GetPostfixSignature (rank);
1160 public static string GetPostfixSignature (int rank)
1162 StringBuilder sb = new StringBuilder ();
1164 for (int i = 1; i < rank; i++) {
1169 return sb.ToString ();
1172 public static ArrayContainer MakeType (TypeSpec element)
1174 return MakeType (element, 1);
1177 public static ArrayContainer MakeType (TypeSpec element, int rank)
1180 var key = new TypeRankPair (element, rank);
1181 if (!instances.TryGetValue (key, out ac)) {
1182 ac = new ArrayContainer (element, rank) {
1183 BaseType = TypeManager.array_type
1186 instances.Add (key, ac);
1192 public static void Reset ()
1194 instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1198 class ReferenceContainer : ElementTypeSpec
1200 static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1202 private ReferenceContainer (TypeSpec element)
1203 : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
1207 public override Type GetMetaInfo ()
1210 info = Element.GetMetaInfo ().MakeByRefType ();
1216 public static ReferenceContainer MakeType (TypeSpec element)
1218 ReferenceContainer pc;
1219 if (!instances.TryGetValue (element, out pc)) {
1220 pc = new ReferenceContainer (element);
1221 instances.Add (element, pc);
1227 public static void Reset ()
1229 instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1233 class PointerContainer : ElementTypeSpec
1235 static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
1237 private PointerContainer (TypeSpec element)
1238 : base (MemberKind.PointerType, element, null)
1240 // It's never CLS-Compliant
1241 state &= ~StateFlags.CLSCompliant_Undetected;
1244 public override Type GetMetaInfo ()
1247 info = Element.GetMetaInfo ().MakePointerType ();
1253 protected override string GetPostfixSignature()
1258 public static PointerContainer MakeType (TypeSpec element)
1260 PointerContainer pc;
1261 if (!instances.TryGetValue (element, out pc)) {
1262 pc = new PointerContainer (element);
1263 instances.Add (element, pc);
1269 public static void Reset ()
1271 instances = new Dictionary<TypeSpec, PointerContainer> ();