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;
16 using MetaType = IKVM.Reflection.Type;
17 using IKVM.Reflection;
19 using MetaType = System.Type;
20 using System.Reflection;
25 public class TypeSpec : MemberSpec
27 protected MetaType info;
28 protected MemberCache cache;
29 protected IList<TypeSpec> ifaces;
32 Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
34 public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
37 // Reflection Emit hacking
38 static readonly Type TypeBuilder;
39 static readonly Type GenericTypeBuilder;
43 var assembly = typeof (object).Assembly;
44 TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder");
45 GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass");
46 if (GenericTypeBuilder == null)
47 GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
51 public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers)
52 : base (kind, declaringType, definition, modifiers)
54 this.declaringType = declaringType;
57 if (definition != null && definition.TypeParametersCount > 0)
58 state |= StateFlags.IsGeneric;
63 public override int Arity {
65 return MemberDefinition.TypeParametersCount;
69 public virtual TypeSpec BaseType {
78 public virtual BuildinTypeSpec.Type BuildinType {
80 return BuildinTypeSpec.Type.None;
84 public bool HasDynamicElement {
86 return (state & StateFlags.HasDynamicElement) != 0;
90 public virtual IList<TypeSpec> Interfaces {
101 return Kind == MemberKind.ArrayType;
105 public bool IsAttribute {
115 if (type.BuildinType == BuildinTypeSpec.Type.Attribute)
118 type = type.base_type;
119 } while (type != null);
125 public bool IsInterface {
127 return Kind == MemberKind.Interface;
131 public bool IsClass {
133 return Kind == MemberKind.Class;
137 public bool IsConstantCompatible {
139 if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
142 switch (BuildinType) {
143 case BuildinTypeSpec.Type.Int:
144 case BuildinTypeSpec.Type.UInt:
145 case BuildinTypeSpec.Type.Long:
146 case BuildinTypeSpec.Type.ULong:
147 case BuildinTypeSpec.Type.Float:
148 case BuildinTypeSpec.Type.Double:
149 case BuildinTypeSpec.Type.Char:
150 case BuildinTypeSpec.Type.Short:
151 case BuildinTypeSpec.Type.Decimal:
152 case BuildinTypeSpec.Type.Bool:
153 case BuildinTypeSpec.Type.SByte:
154 case BuildinTypeSpec.Type.Byte:
155 case BuildinTypeSpec.Type.UShort:
156 case BuildinTypeSpec.Type.Dynamic:
164 public bool IsDelegate {
166 return Kind == MemberKind.Delegate;
171 // Returns true for instances of Expression<T>
173 public virtual bool IsExpressionTreeType {
178 state = value ? state | StateFlags.InflatedExpressionType : state & ~StateFlags.InflatedExpressionType;
184 return Kind == MemberKind.Enum;
189 // Returns true for instances of IList<T>, IEnumerable<T>, ICollection<T>
191 public virtual bool IsGenericIterateInterface {
196 state = value ? state | StateFlags.GenericIterateInterface : state & ~StateFlags.GenericIterateInterface;
200 // TODO: Should probably do
201 // IsGenericType -- recursive
202 // HasTypeParameter -- non-recursive
203 public bool IsGenericOrParentIsGeneric {
209 ts = ts.declaringType;
210 } while (ts != null);
216 public bool IsGenericParameter {
217 get { return Kind == MemberKind.TypeParameter; }
221 // Returns true for instances of Nullable<T>
223 public virtual bool IsNullableType {
228 state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType;
232 public bool IsNested {
233 get { return declaringType != null && Kind != MemberKind.TypeParameter; }
236 public bool IsPointer {
238 return Kind == MemberKind.PointerType;
242 public bool IsSealed {
243 get { return (Modifiers & Modifiers.SEALED) != 0; }
246 public bool IsSpecialRuntimeType {
248 return (state & StateFlags.SpecialRuntimeType) != 0;
251 state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType;
255 public bool IsStruct {
257 return Kind == MemberKind.Struct;
261 public bool IsTypeBuilder {
266 var meta = GetMetaInfo().GetType ();
267 return meta == TypeBuilder || meta == GenericTypeBuilder;
272 public MemberCache MemberCache {
274 if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
275 InitializeMemberCache (false);
281 throw new InternalErrorException ("Membercache reset");
287 public MemberCache MemberCacheTypes {
290 InitializeMemberCache (true);
296 public new ITypeDefinition MemberDefinition {
298 return (ITypeDefinition) definition;
302 // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
303 // remove the property, YES IT WOULD !!!
304 public virtual TypeSpec[] TypeArguments {
305 get { return TypeSpec.EmptyTypes; }
310 public bool AddInterface (TypeSpec iface)
312 if ((state & StateFlags.InterfacesExpanded) != 0)
313 throw new InternalErrorException ("Modifying expanded interface list");
315 if (ifaces == null) {
316 ifaces = new List<TypeSpec> () { iface };
320 if (!ifaces.Contains (iface)) {
328 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
330 if (Kind != MemberKind.Class)
331 throw new InternalErrorException ();
334 return Attribute.DefaultUsageAttribute;
336 AttributeUsageAttribute aua = null;
338 while (type != null) {
339 aua = type.MemberDefinition.GetAttributeUsage (pa);
343 type = type.BaseType;
349 public virtual MetaType GetMetaInfo ()
354 public virtual TypeSpec GetDefinition ()
359 public override string GetSignatureForError ()
364 s = DeclaringType.GetSignatureForError ();
365 } else if (MemberDefinition is AnonymousTypeClass) {
366 return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
368 s = MemberDefinition.Namespace;
371 if (!string.IsNullOrEmpty (s))
374 return s + Name + GetTypeNameSignature ();
377 protected virtual string GetTypeNameSignature ()
382 return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
385 public bool ImplementsInterface (TypeSpec iface, bool variantly)
389 if (t.Interfaces != null) {
390 foreach (TypeSpec i in t.Interfaces) {
391 if (i == iface || TypeSpecComparer.IsEqual (i, iface))
394 if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface))
399 // TODO: Why is it needed when we do it during import
406 protected virtual void InitializeMemberCache (bool onlyTypes)
409 MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
410 } catch (Exception e) {
411 throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ());
415 state |= StateFlags.PendingMemberCacheMembers;
417 state &= ~StateFlags.PendingMemberCacheMembers;
421 // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
422 // comparison is used to hide differences between `object' and `dynamic' for generic
423 // types. Should not be used for comparisons where G<object> != G<dynamic>
425 public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
427 if (dynamicIsObject && baseClass.IsGeneric) {
429 // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
431 // class B : A<object> {}
433 type = type.BaseType;
434 while (type != null) {
435 if (TypeSpecComparer.IsEqual (type, baseClass))
438 type = type.BaseType;
444 while (type != null) {
445 type = type.BaseType;
446 if (type == baseClass)
453 public override MemberSpec InflateMember (TypeParameterInflator inflator)
455 var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
458 // When inflating nested type from inside the type instance will be same
459 // because type parameters are same for all nested types
461 if (DeclaringType == inflator.TypeInstance) {
462 return MakeGenericType (inflator.Context, targs);
465 return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs);
468 public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs)
470 if (targs.Length == 0 && !IsNested)
471 throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
473 InflatedTypeSpec instance;
475 if (inflated_instances == null) {
476 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
479 instance = this as InflatedTypeSpec;
480 if (instance != null) {
482 // Nested types could be inflated on already inflated instances
483 // Caching this type ensured we are using same instance for
484 // inside/outside inflation using local type parameters
486 inflated_instances.Add (TypeArguments, instance);
491 if (!inflated_instances.TryGetValue (targs, out instance)) {
492 if (GetDefinition () != this && !IsNested)
493 throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
494 GetSignatureForError ());
496 instance = new InflatedTypeSpec (context, this, declaringType, targs);
497 inflated_instances.Add (targs, instance);
503 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
508 public override List<TypeSpec> ResolveMissingDependencies ()
510 List<TypeSpec> missing = null;
512 if (Kind == MemberKind.MissingType) {
513 missing = new List<TypeSpec> ();
518 foreach (var targ in TypeArguments) {
519 if (targ.Kind == MemberKind.MissingType) {
521 missing = new List<TypeSpec> ();
527 if (Interfaces != null) {
528 foreach (var iface in Interfaces) {
529 if (iface.Kind == MemberKind.MissingType) {
531 missing = new List<TypeSpec> ();
538 if (missing != null || BaseType == null)
541 return BaseType.ResolveMissingDependencies ();
544 public void SetMetaInfo (MetaType info)
546 if (this.info != null)
547 throw new InternalErrorException ("MetaInfo reset");
552 public void SetExtensionMethodContainer ()
554 modifiers |= Modifiers.METHOD_EXTENSION;
558 public sealed class BuildinTypeSpec : TypeSpec
564 // Ordered carefully for fast compares
592 MulticastDelegate = 23,
607 readonly string name;
609 public BuildinTypeSpec (MemberKind kind, string ns, string name, Type buildinKind)
610 : base (kind, null, null, null, Modifiers.PUBLIC)
612 this.type = buildinKind;
617 public BuildinTypeSpec (string name, Type buildinKind)
618 : this (MemberKind.InternalCompilerType, "", name, buildinKind)
620 // Make all internal types CLS-compliant, non-obsolete, compact
621 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
626 public override int Arity {
632 public override BuildinTypeSpec.Type BuildinType {
638 public string FullName {
640 return ns + '.' + name;
644 public override string Name {
650 public string Namespace {
658 public static bool IsPrimitiveType (TypeSpec type)
660 return type.BuildinType >= Type.FirstPrimitive && type.BuildinType <= Type.LastPrimitive;
663 public static bool IsPrimitiveTypeOrDecimal (TypeSpec type)
665 return type.BuildinType >= Type.FirstPrimitive && type.BuildinType <= Type.Decimal;
668 public override string GetSignatureForError ()
671 case "Int32": return "int";
672 case "Int64": return "long";
673 case "String": return "string";
674 case "Boolean": return "bool";
675 case "Void": return "void";
676 case "Object": return "object";
677 case "UInt32": return "uint";
678 case "Int16": return "short";
679 case "UInt16": return "ushort";
680 case "UInt64": return "ulong";
681 case "Single": return "float";
682 case "Double": return "double";
683 case "Decimal": return "decimal";
684 case "Char": return "char";
685 case "Byte": return "byte";
686 case "SByte": return "sbyte";
696 // Returns the size of type if known, otherwise, 0
698 public static int GetSize (TypeSpec type)
700 switch (type.BuildinType) {
724 public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod)
726 this.definition = td;
728 this.modifiers |= (mod & ~Modifiers.AccessibilityMask);
731 public void SetDefinition (TypeSpec ts)
733 this.definition = ts.MemberDefinition;
734 this.info = ts.GetMetaInfo ();
735 this.BaseType = ts.BaseType;
736 this.Interfaces = ts.Interfaces;
737 this.modifiers = ts.Modifiers;
741 static class TypeSpecComparer
744 // Does strict reference comparion only
746 public static readonly DefaultImpl Default = new DefaultImpl ();
748 public class DefaultImpl : IEqualityComparer<TypeSpec[]>
750 #region IEqualityComparer<TypeSpec[]> Members
752 bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
757 if (x.Length != y.Length)
760 for (int i = 0; i < x.Length; ++i)
767 int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
770 for (int i = 0; i < obj.Length; ++i)
771 hash = (hash << 5) - hash + obj[i].GetHashCode ();
780 // When comparing type signature of overrides or overloads
781 // this version tolerates different MVARs at same position
783 public static class Override
785 public static bool IsEqual (TypeSpec a, TypeSpec b)
791 // Consider the following example:
793 // public abstract class A
795 // public abstract T Foo<T>();
798 // public class B : A
800 // public override U Foo<T>() { return default (U); }
803 // Here, `T' and `U' are method type parameters from different methods
804 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
806 // However, since we're determining whether B.Foo() overrides A.Foo(),
807 // we need to do a signature based comparision and consider them equal.
810 var tp_a = a as TypeParameterSpec;
812 var tp_b = b as TypeParameterSpec;
813 return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
816 var ac_a = a as ArrayContainer;
818 var ac_b = b as ArrayContainer;
819 return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
822 if (a.BuildinType == BuildinTypeSpec.Type.Dynamic || b.BuildinType == BuildinTypeSpec.Type.Dynamic)
823 return b.BuildinType == BuildinTypeSpec.Type.Object || a.BuildinType == BuildinTypeSpec.Type.Object;
825 if (a.MemberDefinition != b.MemberDefinition)
829 for (int i = 0; i < a.TypeArguments.Length; ++i) {
830 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
842 // Compares unordered arrays
844 public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
849 if (a == null || b == null || a.Length != b.Length)
852 for (int ai = 0; ai < a.Length; ++ai) {
854 for (int bi = 0; bi < b.Length; ++bi) {
855 if (IsEqual (a[ai], b[bi])) {
868 public static bool IsEqual (AParametersCollection a, AParametersCollection b)
873 if (a.Count != b.Count)
876 for (int i = 0; i < a.Count; ++i) {
877 if (!IsEqual (a.Types[i], b.Types[i]))
880 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
881 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
890 // Type variance equality comparison
892 public static class Variant
894 public static bool IsEqual (TypeSpec type1, TypeSpec type2)
896 if (!type1.IsGeneric || !type2.IsGeneric)
899 var target_type_def = type2.MemberDefinition;
900 if (type1.MemberDefinition != target_type_def)
903 var t1_targs = type1.TypeArguments;
904 var t2_targs = type2.TypeArguments;
905 var targs_definition = target_type_def.TypeParameters;
907 if (!type1.IsInterface && !type1.IsDelegate) {
911 for (int i = 0; i < targs_definition.Length; ++i) {
912 Variance v = targs_definition[i].Variance;
913 if (v == Variance.None) {
914 if (t1_targs[i] == t2_targs[i])
919 if (v == Variance.Covariant) {
920 if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
922 } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
932 // Checks whether two generic instances may become equal for some
933 // particular instantiation (26.3.1).
935 public static class Unify
938 // Either @a or @b must be generic type
940 public static bool IsEqual (TypeSpec a, TypeSpec b)
942 if (a.MemberDefinition != b.MemberDefinition)
945 var ta = a.TypeArguments;
946 var tb = b.TypeArguments;
947 for (int i = 0; i < ta.Length; i++) {
948 if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
955 static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
957 TypeSpec[] targs = type.TypeArguments;
958 for (int i = 0; i < targs.Length; i++) {
959 if (tparam == targs[i])
962 if (ContainsTypeParameter (tparam, targs[i]))
970 /// Check whether `a' and `b' may become equal generic types.
971 /// The algorithm to do that is a little bit complicated.
973 static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
975 if (a.IsGenericParameter) {
977 // If a is an array of a's type, they may never
984 // If b is a generic parameter or an actual type,
985 // they may become equal:
987 // class X<T,U> : I<T>, I<U>
988 // class X<T> : I<T>, I<float>
990 if (b.IsGenericParameter)
991 return a.DeclaringType == b.DeclaringType;
994 // We're now comparing a type parameter with a
995 // generic instance. They may become equal unless
996 // the type parameter appears anywhere in the
999 // class X<T,U> : I<T>, I<X<U>>
1000 // -> error because you could instanciate it as
1003 // class X<T> : I<T>, I<X<T>> -> ok
1006 return !ContainsTypeParameter (a, b);
1009 if (b.IsGenericParameter)
1010 return MayBecomeEqualGenericTypes (b, a);
1013 // At this point, neither a nor b are a type parameter.
1015 // If one of them is a generic instance, compare them (if the
1016 // other one is not a generic instance, they can never
1019 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
1020 return IsEqual (a, b);
1023 // If both of them are arrays.
1025 var a_ac = a as ArrayContainer;
1027 var b_ac = b as ArrayContainer;
1028 if (b_ac == null || a_ac.Rank != b_ac.Rank)
1031 return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
1035 // Ok, two ordinary types.
1041 public static bool Equals (TypeSpec[] x, TypeSpec[] y)
1046 if (x.Length != y.Length)
1049 for (int i = 0; i < x.Length; ++i)
1050 if (!IsEqual (x[i], y[i]))
1057 // Identity type conversion
1059 // Default reference comparison, it has to be used when comparing
1060 // two possible dynamic/internal types
1062 public static bool IsEqual (TypeSpec a, TypeSpec b)
1065 // This also rejects dynamic == dynamic
1066 return a.Kind != MemberKind.InternalCompilerType || a.BuildinType == BuildinTypeSpec.Type.Dynamic;
1069 if (a == null || b == null)
1073 var a_a = (ArrayContainer) a;
1074 var b_a = b as ArrayContainer;
1078 return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank;
1081 if (!a.IsGeneric || !b.IsGeneric) {
1083 // object and dynamic are considered equivalent there is an identity conversion
1084 // between object and dynamic, and between constructed types that are the same
1085 // when replacing all occurences of dynamic with object.
1087 if (a.BuildinType == BuildinTypeSpec.Type.Dynamic || b.BuildinType == BuildinTypeSpec.Type.Dynamic)
1088 return b.BuildinType == BuildinTypeSpec.Type.Object || a.BuildinType == BuildinTypeSpec.Type.Object;
1093 if (a.MemberDefinition != b.MemberDefinition)
1097 if (!Equals (a.TypeArguments, b.TypeArguments))
1100 a = a.DeclaringType;
1101 b = b.DeclaringType;
1102 } while (a != null);
1108 public interface ITypeDefinition : IMemberDefinition
1110 IAssemblyDefinition DeclaringAssembly { get; }
1111 string Namespace { get; }
1112 int TypeParametersCount { get; }
1113 TypeParameterSpec[] TypeParameters { get; }
1115 TypeSpec GetAttributeCoClass ();
1116 string GetAttributeDefaultMember ();
1117 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
1118 bool IsInternalAsPublic (IAssemblyDefinition assembly);
1119 void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
1122 class InternalType : TypeSpec, ITypeDefinition
1124 public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
1125 public static readonly InternalType Arglist = new InternalType ("__arglist");
1126 public static readonly InternalType MethodGroup = new InternalType ("method group");
1127 public static readonly InternalType NullLiteral = new InternalType ("null");
1128 public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
1130 readonly string name;
1132 InternalType (string name, MemberCache cache)
1138 InternalType (string name)
1139 : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
1142 this.definition = this;
1143 cache = MemberCache.Empty;
1145 // Make all internal types CLS-compliant, non-obsolete
1146 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
1151 public override int Arity {
1157 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1159 throw new NotImplementedException ();
1163 bool IMemberDefinition.IsImported {
1169 public override string Name {
1175 string ITypeDefinition.Namespace {
1181 int ITypeDefinition.TypeParametersCount {
1187 TypeParameterSpec[] ITypeDefinition.TypeParameters {
1195 public override string GetSignatureForError ()
1200 #region ITypeDefinition Members
1202 TypeSpec ITypeDefinition.GetAttributeCoClass ()
1207 string ITypeDefinition.GetAttributeDefaultMember ()
1212 AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
1217 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1219 throw new NotImplementedException ();
1222 void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1224 throw new NotImplementedException ();
1227 string[] IMemberDefinition.ConditionalConditions ()
1232 ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
1237 bool? IMemberDefinition.CLSAttributeValue {
1243 void IMemberDefinition.SetIsAssigned ()
1247 void IMemberDefinition.SetIsUsed ()
1254 public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1256 protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info)
1257 : base (kind, element.DeclaringType, null, info, element.Modifiers)
1259 this.Element = element;
1261 // Some flags can be copied directly from the element
1262 const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected
1263 | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement;
1264 state &= ~shared_flags;
1265 state |= (element.state & shared_flags);
1267 if (element.BuildinType == BuildinTypeSpec.Type.Dynamic)
1268 state |= StateFlags.HasDynamicElement;
1270 // Has to use its own type definition instead of just element definition to
1271 // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1272 this.definition = this;
1274 cache = MemberCache.Empty;
1279 public TypeSpec Element { get; private set; }
1281 public override string Name {
1283 throw new NotSupportedException ();
1289 public override ObsoleteAttribute GetAttributeObsolete ()
1291 return Element.GetAttributeObsolete ();
1294 protected virtual string GetPostfixSignature ()
1299 public override string GetSignatureForError ()
1301 return Element.GetSignatureForError () + GetPostfixSignature ();
1304 public override TypeSpec Mutate (TypeParameterMutator mutator)
1306 var me = Element.Mutate (mutator);
1310 var mutated = (ElementTypeSpec) MemberwiseClone ();
1311 mutated.Element = me;
1312 mutated.info = null;
1316 #region ITypeDefinition Members
1318 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1320 return Element.MemberDefinition.DeclaringAssembly;
1324 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1326 return Element.MemberDefinition.IsInternalAsPublic (assembly);
1329 public string Namespace {
1330 get { throw new NotImplementedException (); }
1333 public int TypeParametersCount {
1339 public TypeParameterSpec[] TypeParameters {
1341 throw new NotSupportedException ();
1345 public TypeSpec GetAttributeCoClass ()
1347 return Element.MemberDefinition.GetAttributeCoClass ();
1350 public string GetAttributeDefaultMember ()
1352 return Element.MemberDefinition.GetAttributeDefaultMember ();
1355 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1357 Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1360 public bool IsImported {
1362 return Element.MemberDefinition.IsImported;
1366 public string[] ConditionalConditions ()
1368 return Element.MemberDefinition.ConditionalConditions ();
1371 bool? IMemberDefinition.CLSAttributeValue {
1373 return Element.MemberDefinition.CLSAttributeValue;
1377 public void SetIsAssigned ()
1379 Element.MemberDefinition.SetIsAssigned ();
1382 public void SetIsUsed ()
1384 Element.MemberDefinition.SetIsUsed ();
1390 public class ArrayContainer : ElementTypeSpec
1392 public struct TypeRankPair : IEquatable<TypeRankPair>
1397 public TypeRankPair (TypeSpec ts, int rank)
1403 public override int GetHashCode ()
1405 return ts.GetHashCode () ^ rank.GetHashCode ();
1408 #region IEquatable<Tuple<T1,T2>> Members
1410 public bool Equals (TypeRankPair other)
1412 return other.ts == ts && other.rank == rank;
1419 readonly ModuleContainer module;
1421 private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
1422 : base (MemberKind.ArrayType, element, null)
1424 this.module = module;
1434 public MethodInfo GetConstructor ()
1436 var mb = module.Builder;
1438 var arg_types = new MetaType[rank];
1439 for (int i = 0; i < rank; i++)
1440 arg_types[i] = module.Compiler.BuildinTypes.Int.GetMetaInfo ();
1442 var ctor = mb.GetArrayMethod (
1443 GetMetaInfo (), Constructor.ConstructorName,
1444 CallingConventions.HasThis,
1450 public MethodInfo GetAddressMethod ()
1452 var mb = module.Builder;
1454 var arg_types = new MetaType[rank];
1455 for (int i = 0; i < rank; i++)
1456 arg_types[i] = module.Compiler.BuildinTypes.Int.GetMetaInfo ();
1458 var address = mb.GetArrayMethod (
1459 GetMetaInfo (), "Address",
1460 CallingConventions.HasThis | CallingConventions.Standard,
1461 ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
1466 public MethodInfo GetGetMethod ()
1468 var mb = module.Builder;
1470 var arg_types = new MetaType[rank];
1471 for (int i = 0; i < rank; i++)
1472 arg_types[i] = module.Compiler.BuildinTypes.Int.GetMetaInfo ();
1474 var get = mb.GetArrayMethod (
1475 GetMetaInfo (), "Get",
1476 CallingConventions.HasThis | CallingConventions.Standard,
1477 Element.GetMetaInfo (), arg_types);
1482 public MethodInfo GetSetMethod ()
1484 var mb = module.Builder;
1486 var arg_types = new MetaType[rank + 1];
1487 for (int i = 0; i < rank; i++)
1488 arg_types[i] = module.Compiler.BuildinTypes.Int.GetMetaInfo ();
1490 arg_types[rank] = Element.GetMetaInfo ();
1492 var set = mb.GetArrayMethod (
1493 GetMetaInfo (), "Set",
1494 CallingConventions.HasThis | CallingConventions.Standard,
1495 module.Compiler.BuildinTypes.Void.GetMetaInfo (), arg_types);
1500 public override MetaType GetMetaInfo ()
1504 info = Element.GetMetaInfo ().MakeArrayType ();
1506 info = Element.GetMetaInfo ().MakeArrayType (rank);
1512 protected override string GetPostfixSignature()
1514 return GetPostfixSignature (rank);
1517 public static string GetPostfixSignature (int rank)
1519 StringBuilder sb = new StringBuilder ();
1521 for (int i = 1; i < rank; i++) {
1526 return sb.ToString ();
1529 public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)
1531 return MakeType (module, element, 1);
1534 public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank)
1537 var key = new TypeRankPair (element, rank);
1538 if (!module.ArraysCache.TryGetValue (key, out ac)) {
1539 ac = new ArrayContainer (module, element, rank) {
1540 BaseType = module.Compiler.BuildinTypes.Array
1543 module.ArraysCache.Add (key, ac);
1550 class ReferenceContainer : ElementTypeSpec
1552 static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1554 private ReferenceContainer (TypeSpec element)
1555 : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
1559 public override MetaType GetMetaInfo ()
1562 info = Element.GetMetaInfo ().MakeByRefType ();
1568 public static ReferenceContainer MakeType (TypeSpec element)
1570 ReferenceContainer pc;
1571 if (!instances.TryGetValue (element, out pc)) {
1572 pc = new ReferenceContainer (element);
1573 instances.Add (element, pc);
1579 public static void Reset ()
1581 instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1585 class PointerContainer : ElementTypeSpec
1587 static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
1589 private PointerContainer (TypeSpec element)
1590 : base (MemberKind.PointerType, element, null)
1592 // It's never CLS-Compliant
1593 state &= ~StateFlags.CLSCompliant_Undetected;
1596 public override MetaType GetMetaInfo ()
1599 info = Element.GetMetaInfo ().MakePointerType ();
1605 protected override string GetPostfixSignature()
1610 public static PointerContainer MakeType (TypeSpec element)
1612 PointerContainer pc;
1613 if (!instances.TryGetValue (element, out pc)) {
1614 pc = new PointerContainer (element);
1615 instances.Add (element, pc);
1621 public static void Reset ()
1623 instances = new Dictionary<TypeSpec, PointerContainer> ();