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 BuiltinTypeSpec.Type BuiltinType {
80 return BuiltinTypeSpec.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 {
112 if (type.BuiltinType == BuiltinTypeSpec.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 (BuiltinType) {
143 case BuiltinTypeSpec.Type.Int:
144 case BuiltinTypeSpec.Type.UInt:
145 case BuiltinTypeSpec.Type.Long:
146 case BuiltinTypeSpec.Type.ULong:
147 case BuiltinTypeSpec.Type.Float:
148 case BuiltinTypeSpec.Type.Double:
149 case BuiltinTypeSpec.Type.Char:
150 case BuiltinTypeSpec.Type.Short:
151 case BuiltinTypeSpec.Type.Decimal:
152 case BuiltinTypeSpec.Type.Bool:
153 case BuiltinTypeSpec.Type.SByte:
154 case BuiltinTypeSpec.Type.Byte:
155 case BuiltinTypeSpec.Type.UShort:
156 case BuiltinTypeSpec.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 {
218 return Kind == MemberKind.TypeParameter;
223 // Returns true for instances of Nullable<T>
225 public virtual bool IsNullableType {
230 state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType;
234 public bool IsNested {
235 get { return declaringType != null && Kind != MemberKind.TypeParameter; }
238 public bool IsPointer {
240 return Kind == MemberKind.PointerType;
244 public bool IsSealed {
245 get { return (Modifiers & Modifiers.SEALED) != 0; }
248 public bool IsSpecialRuntimeType {
250 return (state & StateFlags.SpecialRuntimeType) != 0;
253 state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType;
257 public bool IsStruct {
259 return Kind == MemberKind.Struct;
263 public bool IsTypeBuilder {
268 var meta = GetMetaInfo().GetType ();
269 return meta == TypeBuilder || meta == GenericTypeBuilder;
274 public MemberCache MemberCache {
276 if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
277 InitializeMemberCache (false);
283 throw new InternalErrorException ("Membercache reset");
289 public MemberCache MemberCacheTypes {
292 InitializeMemberCache (true);
298 public new ITypeDefinition MemberDefinition {
300 return (ITypeDefinition) definition;
304 // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
305 // remove the property, YES IT WOULD !!!
306 public virtual TypeSpec[] TypeArguments {
307 get { return TypeSpec.EmptyTypes; }
312 public bool AddInterface (TypeSpec iface)
314 if ((state & StateFlags.InterfacesExpanded) != 0)
315 throw new InternalErrorException ("Modifying expanded interface list");
317 if (ifaces == null) {
318 ifaces = new List<TypeSpec> () { iface };
322 if (!ifaces.Contains (iface)) {
330 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
332 if (Kind != MemberKind.Class)
333 throw new InternalErrorException ();
336 return Attribute.DefaultUsageAttribute;
338 AttributeUsageAttribute aua = null;
340 while (type != null) {
341 aua = type.MemberDefinition.GetAttributeUsage (pa);
345 type = type.BaseType;
351 public virtual MetaType GetMetaInfo ()
356 public virtual TypeSpec GetDefinition ()
361 public override string GetSignatureForDocumentation ()
363 StringBuilder sb = new StringBuilder ();
365 sb.Append (DeclaringType.GetSignatureForDocumentation ());
367 sb.Append (MemberDefinition.Namespace);
375 if (this is InflatedTypeSpec) {
377 for (int i = 0; i < Arity; ++i) {
381 sb.Append (TypeArguments[i].GetSignatureForDocumentation ());
386 sb.Append (Arity.ToString ());
390 return sb.ToString ();
393 public string GetExplicitNameSignatureForDocumentation ()
395 StringBuilder sb = new StringBuilder ();
397 sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ());
398 } else if (MemberDefinition.Namespace != null) {
399 sb.Append (MemberDefinition.Namespace.Replace ('.', '#'));
408 for (int i = 0; i < Arity; ++i) {
412 sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ());
417 return sb.ToString ();
420 public override string GetSignatureForError ()
425 s = DeclaringType.GetSignatureForError ();
426 } else if (MemberDefinition is AnonymousTypeClass) {
427 return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
429 s = MemberDefinition.Namespace;
432 if (!string.IsNullOrEmpty (s))
435 return s + Name + GetTypeNameSignature ();
438 public string GetSignatureForErrorIncludingAssemblyName ()
440 return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName);
443 protected virtual string GetTypeNameSignature ()
448 return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
451 public bool ImplementsInterface (TypeSpec iface, bool variantly)
455 if (t.Interfaces != null) {
456 foreach (TypeSpec i in t.Interfaces) {
457 if (i == iface || TypeSpecComparer.IsEqual (i, iface))
460 if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface))
465 // TODO: Why is it needed when we do it during import
472 protected virtual void InitializeMemberCache (bool onlyTypes)
475 MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
476 } catch (Exception e) {
477 throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ());
481 state |= StateFlags.PendingMemberCacheMembers;
483 state &= ~StateFlags.PendingMemberCacheMembers;
487 // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
488 // comparison is used to hide differences between `object' and `dynamic' for generic
489 // types. Should not be used for comparisons where G<object> != G<dynamic>
491 public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
493 if (dynamicIsObject && baseClass.IsGeneric) {
495 // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
497 // class B : A<object> {}
499 type = type.BaseType;
500 while (type != null) {
501 if (TypeSpecComparer.IsEqual (type, baseClass))
504 type = type.BaseType;
510 while (type != null) {
511 type = type.BaseType;
512 if (type == baseClass)
519 public static bool IsReferenceType (TypeSpec t)
522 case MemberKind.TypeParameter:
523 return ((TypeParameterSpec) t).IsReferenceType;
524 case MemberKind.Struct:
525 case MemberKind.Enum:
527 case MemberKind.InternalCompilerType:
529 // Null is considered to be a reference type
531 return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
537 public static bool IsValueType (TypeSpec t)
540 case MemberKind.TypeParameter:
541 return ((TypeParameterSpec) t).IsValueType;
542 case MemberKind.Struct:
543 case MemberKind.Enum:
550 public override MemberSpec InflateMember (TypeParameterInflator inflator)
552 var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
555 // When inflating nested type from inside the type instance will be same
556 // because type parameters are same for all nested types
558 if (DeclaringType == inflator.TypeInstance) {
559 return MakeGenericType (inflator.Context, targs);
562 return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs);
565 public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs)
567 if (targs.Length == 0 && !IsNested)
568 throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
570 InflatedTypeSpec instance;
572 if (inflated_instances == null) {
573 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
576 instance = this as InflatedTypeSpec;
577 if (instance != null) {
579 // Nested types could be inflated on already inflated instances
580 // Caching this type ensured we are using same instance for
581 // inside/outside inflation using local type parameters
583 inflated_instances.Add (TypeArguments, instance);
588 if (!inflated_instances.TryGetValue (targs, out instance)) {
589 if (GetDefinition () != this && !IsNested)
590 throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
591 GetSignatureForError ());
593 instance = new InflatedTypeSpec (context, this, declaringType, targs);
594 inflated_instances.Add (targs, instance);
600 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
605 public override List<TypeSpec> ResolveMissingDependencies ()
607 List<TypeSpec> missing = null;
609 if (Kind == MemberKind.MissingType) {
610 missing = new List<TypeSpec> ();
615 foreach (var targ in TypeArguments) {
616 if (targ.Kind == MemberKind.MissingType) {
618 missing = new List<TypeSpec> ();
624 if (Interfaces != null) {
625 foreach (var iface in Interfaces) {
626 if (iface.Kind == MemberKind.MissingType) {
628 missing = new List<TypeSpec> ();
635 if (missing != null || BaseType == null)
638 return BaseType.ResolveMissingDependencies ();
641 public void SetMetaInfo (MetaType info)
643 if (this.info != null)
644 throw new InternalErrorException ("MetaInfo reset");
649 public void SetExtensionMethodContainer ()
651 modifiers |= Modifiers.METHOD_EXTENSION;
655 public sealed class BuiltinTypeSpec : TypeSpec
661 // Ordered carefully for fast compares
689 MulticastDelegate = 23,
702 readonly string name;
704 public BuiltinTypeSpec (MemberKind kind, string ns, string name, Type builtinKind)
705 : base (kind, null, null, null, Modifiers.PUBLIC)
707 this.type = builtinKind;
712 public BuiltinTypeSpec (string name, Type builtinKind)
713 : this (MemberKind.InternalCompilerType, "", name, builtinKind)
715 // Make all internal types CLS-compliant, non-obsolete, compact
716 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
721 public override int Arity {
727 public override BuiltinTypeSpec.Type BuiltinType {
733 public string FullName {
735 return ns + '.' + name;
739 public override string Name {
745 public string Namespace {
753 public static bool IsPrimitiveType (TypeSpec type)
755 return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.LastPrimitive;
758 public static bool IsPrimitiveTypeOrDecimal (TypeSpec type)
760 return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.Decimal;
763 public override string GetSignatureForError ()
766 case "Int32": return "int";
767 case "Int64": return "long";
768 case "String": return "string";
769 case "Boolean": return "bool";
770 case "Void": return "void";
771 case "Object": return "object";
772 case "UInt32": return "uint";
773 case "Int16": return "short";
774 case "UInt16": return "ushort";
775 case "UInt64": return "ulong";
776 case "Single": return "float";
777 case "Double": return "double";
778 case "Decimal": return "decimal";
779 case "Char": return "char";
780 case "Byte": return "byte";
781 case "SByte": return "sbyte";
791 // Returns the size of type if known, otherwise, 0
793 public static int GetSize (TypeSpec type)
795 switch (type.BuiltinType) {
819 public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod)
821 this.definition = td;
823 this.modifiers |= (mod & ~Modifiers.AccessibilityMask);
826 public void SetDefinition (TypeSpec ts)
828 this.definition = ts.MemberDefinition;
829 this.info = ts.GetMetaInfo ();
830 this.BaseType = ts.BaseType;
831 this.Interfaces = ts.Interfaces;
832 this.modifiers = ts.Modifiers;
836 static class TypeSpecComparer
839 // Does strict reference comparion only
841 public static readonly DefaultImpl Default = new DefaultImpl ();
843 public class DefaultImpl : IEqualityComparer<TypeSpec[]>
845 #region IEqualityComparer<TypeSpec[]> Members
847 bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
852 if (x.Length != y.Length)
855 for (int i = 0; i < x.Length; ++i)
862 int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
865 for (int i = 0; i < obj.Length; ++i)
866 hash = (hash << 5) - hash + obj[i].GetHashCode ();
875 // When comparing type signature of overrides or overloads
876 // this version tolerates different MVARs at same position
878 public static class Override
880 public static bool IsEqual (TypeSpec a, TypeSpec b)
886 // Consider the following example:
888 // public abstract class A
890 // public abstract T Foo<T>();
893 // public class B : A
895 // public override U Foo<T>() { return default (U); }
898 // Here, `T' and `U' are method type parameters from different methods
899 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
901 // However, since we're determining whether B.Foo() overrides A.Foo(),
902 // we need to do a signature based comparision and consider them equal.
905 var tp_a = a as TypeParameterSpec;
907 var tp_b = b as TypeParameterSpec;
908 return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
911 var ac_a = a as ArrayContainer;
913 var ac_b = b as ArrayContainer;
914 return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
917 if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
918 return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
920 if (a.MemberDefinition != b.MemberDefinition)
924 for (int i = 0; i < a.TypeArguments.Length; ++i) {
925 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
937 // Compares unordered arrays
939 public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
944 if (a == null || b == null || a.Length != b.Length)
947 for (int ai = 0; ai < a.Length; ++ai) {
949 for (int bi = 0; bi < b.Length; ++bi) {
950 if (IsEqual (a[ai], b[bi])) {
963 public static bool IsEqual (AParametersCollection a, AParametersCollection b)
968 if (a.Count != b.Count)
971 for (int i = 0; i < a.Count; ++i) {
972 if (!IsEqual (a.Types[i], b.Types[i]))
975 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
976 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
985 // Type variance equality comparison
987 public static class Variant
989 public static bool IsEqual (TypeSpec type1, TypeSpec type2)
991 if (!type1.IsGeneric || !type2.IsGeneric)
994 var target_type_def = type2.MemberDefinition;
995 if (type1.MemberDefinition != target_type_def)
998 var t1_targs = type1.TypeArguments;
999 var t2_targs = type2.TypeArguments;
1000 var targs_definition = target_type_def.TypeParameters;
1002 if (!type1.IsInterface && !type1.IsDelegate) {
1006 for (int i = 0; i < targs_definition.Length; ++i) {
1007 Variance v = targs_definition[i].Variance;
1008 if (v == Variance.None) {
1009 if (t1_targs[i] == t2_targs[i])
1014 if (v == Variance.Covariant) {
1015 if (!Convert.ImplicitReferenceConversionExists (t1_targs[i], t2_targs[i]))
1017 } else if (!Convert.ImplicitReferenceConversionExists (t2_targs[i], t1_targs[i])) {
1027 // Checks whether two generic instances may become equal for some
1028 // particular instantiation (26.3.1).
1030 public static class Unify
1033 // Either @a or @b must be generic type
1035 public static bool IsEqual (TypeSpec a, TypeSpec b)
1037 if (a.MemberDefinition != b.MemberDefinition) {
1038 var base_ifaces = a.Interfaces;
1039 if (base_ifaces != null) {
1040 foreach (var base_iface in base_ifaces) {
1041 if (base_iface.Arity > 0 && IsEqual (base_iface, b))
1049 var ta = a.TypeArguments;
1050 var tb = b.TypeArguments;
1051 for (int i = 0; i < ta.Length; i++) {
1052 if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
1059 static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
1061 TypeSpec[] targs = type.TypeArguments;
1062 for (int i = 0; i < targs.Length; i++) {
1063 if (tparam == targs[i])
1066 if (ContainsTypeParameter (tparam, targs[i]))
1074 /// Check whether `a' and `b' may become equal generic types.
1075 /// The algorithm to do that is a little bit complicated.
1077 static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
1079 if (a.IsGenericParameter) {
1081 // If a is an array of a's type, they may never
1088 // If b is a generic parameter or an actual type,
1089 // they may become equal:
1091 // class X<T,U> : I<T>, I<U>
1092 // class X<T> : I<T>, I<float>
1094 if (b.IsGenericParameter)
1095 return a != b && a.DeclaringType == b.DeclaringType;
1098 // We're now comparing a type parameter with a
1099 // generic instance. They may become equal unless
1100 // the type parameter appears anywhere in the
1101 // generic instance:
1103 // class X<T,U> : I<T>, I<X<U>>
1104 // -> error because you could instanciate it as
1107 // class X<T> : I<T>, I<X<T>> -> ok
1110 return !ContainsTypeParameter (a, b);
1113 if (b.IsGenericParameter)
1114 return MayBecomeEqualGenericTypes (b, a);
1117 // At this point, neither a nor b are a type parameter.
1119 // If one of them is a generic instance, compare them (if the
1120 // other one is not a generic instance, they can never
1123 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
1124 return IsEqual (a, b);
1127 // If both of them are arrays.
1129 var a_ac = a as ArrayContainer;
1131 var b_ac = b as ArrayContainer;
1132 if (b_ac == null || a_ac.Rank != b_ac.Rank)
1135 return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
1139 // Ok, two ordinary types.
1145 public static bool Equals (TypeSpec[] x, TypeSpec[] y)
1150 if (x.Length != y.Length)
1153 for (int i = 0; i < x.Length; ++i)
1154 if (!IsEqual (x[i], y[i]))
1161 // Identity type conversion
1163 // Default reference comparison, it has to be used when comparing
1164 // two possible dynamic/internal types
1166 public static bool IsEqual (TypeSpec a, TypeSpec b)
1169 // This also rejects dynamic == dynamic
1170 return a.Kind != MemberKind.InternalCompilerType || a.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
1173 if (a == null || b == null)
1177 var a_a = (ArrayContainer) a;
1178 var b_a = b as ArrayContainer;
1182 return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element);
1185 if (!a.IsGeneric || !b.IsGeneric) {
1187 // object and dynamic are considered equivalent there is an identity conversion
1188 // between object and dynamic, and between constructed types that are the same
1189 // when replacing all occurences of dynamic with object.
1191 if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1192 return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
1197 if (a.MemberDefinition != b.MemberDefinition)
1201 if (!Equals (a.TypeArguments, b.TypeArguments))
1204 a = a.DeclaringType;
1205 b = b.DeclaringType;
1206 } while (a != null);
1212 public interface ITypeDefinition : IMemberDefinition
1214 IAssemblyDefinition DeclaringAssembly { get; }
1215 string Namespace { get; }
1216 int TypeParametersCount { get; }
1217 TypeParameterSpec[] TypeParameters { get; }
1219 TypeSpec GetAttributeCoClass ();
1220 string GetAttributeDefaultMember ();
1221 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
1222 bool IsInternalAsPublic (IAssemblyDefinition assembly);
1223 void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
1226 class InternalType : TypeSpec, ITypeDefinition
1228 public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
1229 public static readonly InternalType Arglist = new InternalType ("__arglist");
1230 public static readonly InternalType MethodGroup = new InternalType ("method group");
1231 public static readonly InternalType NullLiteral = new InternalType ("null");
1232 public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
1233 public static readonly InternalType Namespace = new InternalType ("<namespace>");
1235 readonly string name;
1237 InternalType (string name, MemberCache cache)
1243 InternalType (string name)
1244 : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
1247 this.definition = this;
1248 cache = MemberCache.Empty;
1250 // Make all internal types CLS-compliant, non-obsolete
1251 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
1256 public override int Arity {
1262 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1264 throw new NotImplementedException ();
1268 bool IMemberDefinition.IsImported {
1274 public override string Name {
1280 string ITypeDefinition.Namespace {
1286 int ITypeDefinition.TypeParametersCount {
1292 TypeParameterSpec[] ITypeDefinition.TypeParameters {
1300 public override string GetSignatureForError ()
1305 #region ITypeDefinition Members
1307 TypeSpec ITypeDefinition.GetAttributeCoClass ()
1312 string ITypeDefinition.GetAttributeDefaultMember ()
1317 AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
1322 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1324 throw new NotImplementedException ();
1327 void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1329 throw new NotImplementedException ();
1332 string[] IMemberDefinition.ConditionalConditions ()
1337 ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
1342 bool? IMemberDefinition.CLSAttributeValue {
1348 void IMemberDefinition.SetIsAssigned ()
1352 void IMemberDefinition.SetIsUsed ()
1359 public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1361 protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info)
1362 : base (kind, element.DeclaringType, null, info, element.Modifiers)
1364 this.Element = element;
1366 // Some flags can be copied directly from the element
1367 const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected
1368 | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement;
1369 state &= ~shared_flags;
1370 state |= (element.state & shared_flags);
1372 if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1373 state |= StateFlags.HasDynamicElement;
1375 // Has to use its own type definition instead of just element definition to
1376 // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1377 this.definition = this;
1379 cache = MemberCache.Empty;
1384 public TypeSpec Element { get; private set; }
1386 public override string Name {
1388 throw new NotSupportedException ();
1394 public override ObsoleteAttribute GetAttributeObsolete ()
1396 return Element.GetAttributeObsolete ();
1399 protected virtual string GetPostfixSignature ()
1404 public override string GetSignatureForDocumentation ()
1406 return Element.GetSignatureForDocumentation () + GetPostfixSignature ();
1409 public override string GetSignatureForError ()
1411 return Element.GetSignatureForError () + GetPostfixSignature ();
1414 public override TypeSpec Mutate (TypeParameterMutator mutator)
1416 var me = Element.Mutate (mutator);
1420 var mutated = (ElementTypeSpec) MemberwiseClone ();
1421 mutated.Element = me;
1422 mutated.info = null;
1426 #region ITypeDefinition Members
1428 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1430 return Element.MemberDefinition.DeclaringAssembly;
1434 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1436 return Element.MemberDefinition.IsInternalAsPublic (assembly);
1439 public string Namespace {
1440 get { throw new NotImplementedException (); }
1443 public int TypeParametersCount {
1449 public TypeParameterSpec[] TypeParameters {
1451 throw new NotSupportedException ();
1455 public TypeSpec GetAttributeCoClass ()
1457 return Element.MemberDefinition.GetAttributeCoClass ();
1460 public string GetAttributeDefaultMember ()
1462 return Element.MemberDefinition.GetAttributeDefaultMember ();
1465 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1467 Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1470 public bool IsImported {
1472 return Element.MemberDefinition.IsImported;
1476 public string[] ConditionalConditions ()
1478 return Element.MemberDefinition.ConditionalConditions ();
1481 bool? IMemberDefinition.CLSAttributeValue {
1483 return Element.MemberDefinition.CLSAttributeValue;
1487 public void SetIsAssigned ()
1489 Element.MemberDefinition.SetIsAssigned ();
1492 public void SetIsUsed ()
1494 Element.MemberDefinition.SetIsUsed ();
1500 public class ArrayContainer : ElementTypeSpec
1502 public struct TypeRankPair : IEquatable<TypeRankPair>
1507 public TypeRankPair (TypeSpec ts, int rank)
1513 public override int GetHashCode ()
1515 return ts.GetHashCode () ^ rank.GetHashCode ();
1518 #region IEquatable<Tuple<T1,T2>> Members
1520 public bool Equals (TypeRankPair other)
1522 return other.ts == ts && other.rank == rank;
1529 readonly ModuleContainer module;
1531 private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
1532 : base (MemberKind.ArrayType, element, null)
1534 this.module = module;
1544 public MethodInfo GetConstructor ()
1546 var mb = module.Builder;
1548 var arg_types = new MetaType[rank];
1549 for (int i = 0; i < rank; i++)
1550 arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1552 var ctor = mb.GetArrayMethod (
1553 GetMetaInfo (), Constructor.ConstructorName,
1554 CallingConventions.HasThis,
1560 public MethodInfo GetAddressMethod ()
1562 var mb = module.Builder;
1564 var arg_types = new MetaType[rank];
1565 for (int i = 0; i < rank; i++)
1566 arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1568 var address = mb.GetArrayMethod (
1569 GetMetaInfo (), "Address",
1570 CallingConventions.HasThis | CallingConventions.Standard,
1571 ReferenceContainer.MakeType (module, Element).GetMetaInfo (), arg_types);
1576 public MethodInfo GetGetMethod ()
1578 var mb = module.Builder;
1580 var arg_types = new MetaType[rank];
1581 for (int i = 0; i < rank; i++)
1582 arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1584 var get = mb.GetArrayMethod (
1585 GetMetaInfo (), "Get",
1586 CallingConventions.HasThis | CallingConventions.Standard,
1587 Element.GetMetaInfo (), arg_types);
1592 public MethodInfo GetSetMethod ()
1594 var mb = module.Builder;
1596 var arg_types = new MetaType[rank + 1];
1597 for (int i = 0; i < rank; i++)
1598 arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1600 arg_types[rank] = Element.GetMetaInfo ();
1602 var set = mb.GetArrayMethod (
1603 GetMetaInfo (), "Set",
1604 CallingConventions.HasThis | CallingConventions.Standard,
1605 module.Compiler.BuiltinTypes.Void.GetMetaInfo (), arg_types);
1610 public override MetaType GetMetaInfo ()
1614 info = Element.GetMetaInfo ().MakeArrayType ();
1616 info = Element.GetMetaInfo ().MakeArrayType (rank);
1622 protected override string GetPostfixSignature()
1624 return GetPostfixSignature (rank);
1627 public static string GetPostfixSignature (int rank)
1629 StringBuilder sb = new StringBuilder ();
1631 for (int i = 1; i < rank; i++) {
1636 return sb.ToString ();
1639 public override string GetSignatureForDocumentation ()
1642 List<int> ranks = new List<int> (2);
1645 while (e is ArrayContainer) {
1646 var ac = (ArrayContainer) e;
1647 ranks.Add (ac.rank);
1651 StringBuilder sb = new StringBuilder (e.GetSignatureForDocumentation ());
1652 for (int r = 0; r < ranks.Count; ++r) {
1654 for (int i = 1; i < ranks[r]; i++) {
1663 return sb.ToString ();
1666 public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)
1668 return MakeType (module, element, 1);
1671 public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank)
1674 var key = new TypeRankPair (element, rank);
1675 if (!module.ArrayTypesCache.TryGetValue (key, out ac)) {
1676 ac = new ArrayContainer (module, element, rank) {
1677 BaseType = module.Compiler.BuiltinTypes.Array
1680 module.ArrayTypesCache.Add (key, ac);
1687 class ReferenceContainer : ElementTypeSpec
1689 private ReferenceContainer (TypeSpec element)
1690 : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
1694 public override MetaType GetMetaInfo ()
1697 info = Element.GetMetaInfo ().MakeByRefType ();
1703 public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element)
1705 ReferenceContainer pc;
1706 if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) {
1707 pc = new ReferenceContainer (element);
1708 module.ReferenceTypesCache.Add (element, pc);
1715 class PointerContainer : ElementTypeSpec
1717 private PointerContainer (TypeSpec element)
1718 : base (MemberKind.PointerType, element, null)
1720 // It's never CLS-Compliant
1721 state &= ~StateFlags.CLSCompliant_Undetected;
1724 public override MetaType GetMetaInfo ()
1727 info = Element.GetMetaInfo ().MakePointerType ();
1733 protected override string GetPostfixSignature()
1738 public static PointerContainer MakeType (ModuleContainer module, TypeSpec element)
1740 PointerContainer pc;
1741 if (!module.PointerTypesCache.TryGetValue (element, out pc)) {
1742 pc = new PointerContainer (element);
1743 module.PointerTypesCache.Add (element, pc);