PageRenderTime 101ms CodeModel.GetById 39ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs

http://github.com/icsharpcode/ILSpy
C# | 2021 lines | 1450 code | 348 blank | 223 comment | 338 complexity | e7bf41e3000348d501bc0a9cc8fc9872 MD5 | raw file
   1//
   2// typespec.cs: Type specification
   3//
   4// Authors: Marek Safar (marek.safar@gmail.com)
   5//
   6// Dual licensed under the terms of the MIT X11 or GNU GPL
   7//
   8// Copyright 2010 Novell, Inc
   9// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  10//
  11
  12using System;
  13using System.Collections.Generic;
  14using System.Text;
  15using System.Linq;
  16
  17#if STATIC
  18using MetaType = IKVM.Reflection.Type;
  19using IKVM.Reflection;
  20#else
  21using MetaType = System.Type;
  22using System.Reflection;
  23#endif
  24
  25namespace Mono.CSharp
  26{
  27	//
  28	// Inflated or non-inflated representation of any type. 
  29	//
  30	public class TypeSpec : MemberSpec
  31	{
  32		protected MetaType info;
  33		protected MemberCache cache;
  34		protected IList<TypeSpec> ifaces;
  35		TypeSpec base_type;
  36
  37		Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
  38
  39		public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
  40
  41#if !STATIC
  42		// Reflection Emit hacking
  43		static readonly Type TypeBuilder;
  44		static readonly Type GenericTypeBuilder;
  45
  46		static TypeSpec ()
  47		{
  48			var assembly = typeof (object).Assembly;
  49			TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder");
  50			GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass");
  51			if (GenericTypeBuilder == null)
  52				GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
  53		}
  54#endif
  55
  56		public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers)
  57			: base (kind, declaringType, definition, modifiers)
  58		{
  59			this.declaringType = declaringType;
  60			this.info = info;
  61
  62			if (definition != null && definition.TypeParametersCount > 0)
  63				state |= StateFlags.IsGeneric;
  64		}
  65
  66		#region Properties
  67
  68		public override int Arity {
  69			get {
  70				return MemberDefinition.TypeParametersCount;
  71			}
  72		}
  73
  74		public virtual TypeSpec BaseType {
  75			get {
  76				return base_type;
  77			}
  78			set {
  79				base_type = value;
  80			}
  81		}
  82
  83		public virtual BuiltinTypeSpec.Type BuiltinType {
  84			get {
  85				return BuiltinTypeSpec.Type.None;
  86			}
  87		}
  88
  89		public bool HasDynamicElement {
  90			get {
  91				return (state & StateFlags.HasDynamicElement) != 0;
  92			}
  93		}
  94
  95		//
  96		// Returns a list of all interfaces including
  97		// interfaces from base type or base interfaces
  98		//
  99		public virtual IList<TypeSpec> Interfaces {
 100			get {
 101				if ((state & StateFlags.InterfacesImported) == 0) {
 102					state |= StateFlags.InterfacesImported;
 103
 104					//
 105					// Delay interfaces expansion to save memory and once all
 106					// base types has been imported to avoid problems where
 107					// interface references type before its base was imported
 108					//
 109					var imported = MemberDefinition as ImportedTypeDefinition;
 110					if (imported != null && Kind != MemberKind.MissingType)
 111						imported.DefineInterfaces (this);
 112
 113				}
 114
 115				return ifaces;
 116			}
 117			set {
 118				ifaces = value;
 119			}
 120		}
 121
 122		public bool IsArray {
 123			get {
 124				return Kind == MemberKind.ArrayType;
 125			}
 126		}
 127
 128		public bool IsAttribute {
 129			get {
 130				if (!IsClass)
 131					return false;
 132
 133				var type = this;
 134				do {
 135					if (type.BuiltinType == BuiltinTypeSpec.Type.Attribute)
 136						return true;
 137
 138					if (type.IsGeneric)
 139						return false;
 140					
 141					type = type.base_type;
 142				} while (type != null);
 143
 144				return false;
 145			}
 146		}
 147
 148		public bool IsInterface {
 149			get {
 150				return Kind == MemberKind.Interface;
 151			}
 152		}
 153
 154		public bool IsClass {
 155			get {
 156				return Kind == MemberKind.Class;
 157			}
 158		}
 159
 160		public bool IsConstantCompatible {
 161			get {
 162				if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
 163					return true;
 164
 165				switch (BuiltinType) {
 166				case BuiltinTypeSpec.Type.Int:
 167				case BuiltinTypeSpec.Type.UInt:
 168				case BuiltinTypeSpec.Type.Long:
 169				case BuiltinTypeSpec.Type.ULong:
 170				case BuiltinTypeSpec.Type.Float:
 171				case BuiltinTypeSpec.Type.Double:
 172				case BuiltinTypeSpec.Type.Char:
 173				case BuiltinTypeSpec.Type.Short:
 174				case BuiltinTypeSpec.Type.Decimal:
 175				case BuiltinTypeSpec.Type.Bool:
 176				case BuiltinTypeSpec.Type.SByte:
 177				case BuiltinTypeSpec.Type.Byte:
 178				case BuiltinTypeSpec.Type.UShort:
 179				case BuiltinTypeSpec.Type.Dynamic:
 180					return true;
 181				}
 182
 183				return false;
 184			}
 185		}
 186
 187		public bool IsDelegate {
 188			get {
 189				return Kind == MemberKind.Delegate;
 190			}
 191		}
 192
 193		//
 194		// Returns true for instances of Expression<T>
 195		//
 196		public virtual bool IsExpressionTreeType {
 197			get {
 198				return false;
 199			}
 200			set {
 201				state = value ? state | StateFlags.InflatedExpressionType : state & ~StateFlags.InflatedExpressionType;
 202			}
 203		}
 204
 205		public bool IsEnum {
 206			get {
 207				return Kind == MemberKind.Enum;
 208			}
 209		}
 210
 211		//
 212		// Returns true for instances of IList<T>, IEnumerable<T>, ICollection<T>
 213		//
 214		public virtual bool IsArrayGenericInterface {
 215			get {
 216				return false;
 217			}
 218			set {
 219				state = value ? state | StateFlags.GenericIterateInterface : state & ~StateFlags.GenericIterateInterface;
 220			}
 221		}
 222
 223		//
 224		// Returns true for instances of System.Threading.Tasks.Task<T>
 225		//
 226		public virtual bool IsGenericTask {
 227			get {
 228				return false;
 229			}
 230			set {
 231				state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask;
 232			}
 233		}
 234
 235		// TODO: Should probably do
 236		// IsGenericType -- recursive
 237		// HasTypeParameter -- non-recursive
 238		public bool IsGenericOrParentIsGeneric {
 239			get {
 240				var ts = this;
 241				do {
 242					if (ts.IsGeneric)
 243						return true;
 244					ts = ts.declaringType;
 245				} while (ts != null);
 246
 247				return false;
 248			}
 249		}
 250
 251		public bool IsGenericParameter {
 252			get {
 253				return Kind == MemberKind.TypeParameter;
 254			}
 255		}
 256
 257		//
 258		// Returns true for instances of Nullable<T>
 259		//
 260		public virtual bool IsNullableType {
 261			get {
 262				return false;
 263			}
 264			set {
 265				state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType;
 266			}
 267		}
 268
 269		public bool IsNested {
 270			get { return declaringType != null && Kind != MemberKind.TypeParameter; }
 271		}
 272
 273		public bool IsPointer {
 274			get {
 275				return Kind == MemberKind.PointerType;
 276			}
 277		}
 278
 279		public bool IsSealed {
 280			get { return (Modifiers & Modifiers.SEALED) != 0; }
 281		}
 282
 283		public bool IsSpecialRuntimeType {
 284			get {
 285				return (state & StateFlags.SpecialRuntimeType) != 0;
 286			}
 287			set {
 288				state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType;
 289			}
 290		}
 291
 292		public bool IsStruct {
 293			get { 
 294				return Kind == MemberKind.Struct;
 295			}
 296		}
 297
 298		public bool IsStructOrEnum {
 299			get {
 300				return (Kind & (MemberKind.Struct | MemberKind.Enum)) != 0;
 301			}
 302		}
 303
 304		public bool IsTypeBuilder {
 305			get {
 306#if STATIC
 307				return true;
 308#else
 309				var meta = GetMetaInfo().GetType ();
 310				return meta == TypeBuilder || meta == GenericTypeBuilder;
 311#endif
 312			}
 313		}
 314
 315		//
 316		// Whether a type is unmanaged. This is used by the unsafe code
 317		//
 318		public bool IsUnmanaged {
 319			get {
 320				if (IsPointer)
 321					return ((ElementTypeSpec) this).Element.IsUnmanaged;
 322
 323				var ds = MemberDefinition as TypeDefinition;
 324				if (ds != null)
 325					return ds.IsUnmanagedType ();
 326
 327				if (Kind == MemberKind.Void)
 328					return true;
 329
 330				if (Kind == MemberKind.TypeParameter)
 331					return false;
 332
 333				if (IsNested && DeclaringType.IsGenericOrParentIsGeneric)
 334					return false;
 335
 336				return IsValueType (this);
 337			}
 338		}
 339
 340		//
 341		// A cache of all type members (including nested types)
 342		//
 343		public MemberCache MemberCache {
 344			get {
 345				if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
 346					InitializeMemberCache (false);
 347
 348				return cache;
 349			}
 350			set {
 351				if (cache != null)
 352					throw new InternalErrorException ("Membercache reset");
 353
 354				cache = value;
 355			}
 356		}
 357
 358		public MemberCache MemberCacheTypes {
 359			get {
 360				if (cache == null)
 361					InitializeMemberCache (true);
 362
 363				return cache;
 364			}
 365		}	
 366
 367		public new ITypeDefinition MemberDefinition {
 368			get {
 369				return (ITypeDefinition) definition;
 370			}
 371		}
 372
 373		// TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
 374		// remove the property, YES IT WOULD !!!
 375		public virtual TypeSpec[] TypeArguments {
 376			get { return TypeSpec.EmptyTypes; }
 377		}
 378
 379		#endregion
 380
 381		public virtual bool AddInterface (TypeSpec iface)
 382		{
 383			if ((state & StateFlags.InterfacesExpanded) != 0)
 384				throw new InternalErrorException ("Modifying expanded interface list");
 385
 386			if (ifaces == null) {
 387				ifaces = new List<TypeSpec> { iface };
 388				return true;
 389			}
 390
 391			if (!ifaces.Contains (iface)) {
 392				ifaces.Add (iface);
 393				return true;
 394			}
 395
 396			return false;
 397		}
 398
 399		//
 400		// Special version used during type definition
 401		//
 402		public bool AddInterfaceDefined (TypeSpec iface)
 403		{
 404			if (!AddInterface (iface))
 405				return false;
 406
 407			//
 408			// We can get into a situation where a type is inflated before
 409			// its interfaces are resoved. Consider this situation
 410			//
 411			// class A<T> : X<A<int>>, IFoo {}
 412			//
 413			// When resolving base class of X`1 we inflate context type A`1
 414			// All this happens before we even hit IFoo resolve. Without
 415			// additional expansion any inside usage of A<T> would miss IFoo
 416			// interface because it comes from early inflated A`1 definition.
 417			//
 418			if (inflated_instances != null) {
 419				//
 420				// Inflate only existing instances not any new instances added
 421				// during AddInterface
 422				//
 423				var inflated_existing = inflated_instances.Values.ToArray ();
 424				foreach (var inflated in inflated_existing) {
 425					inflated.AddInterface (iface);
 426				}
 427			}
 428
 429			return true;
 430		}
 431
 432		//
 433		// Returns all type arguments, usefull for nested types
 434		//
 435		public static TypeSpec[] GetAllTypeArguments (TypeSpec type)
 436		{
 437			IList<TypeSpec> targs = TypeSpec.EmptyTypes;
 438
 439			do {
 440				if (type.Arity > 0) {
 441					if (targs.Count == 0) {
 442						targs = type.TypeArguments;
 443					} else {
 444						var list = targs as List<TypeSpec> ?? new List<TypeSpec> (targs);
 445						list.AddRange (type.TypeArguments);
 446						targs = list;
 447					}
 448				}
 449
 450				type = type.declaringType;
 451			} while (type != null);
 452
 453			return targs as TypeSpec[] ?? ((List<TypeSpec>) targs).ToArray ();
 454		}
 455
 456		public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
 457		{
 458			if (Kind != MemberKind.Class)
 459				throw new InternalErrorException ();
 460
 461			if (!pa.IsDefined)
 462				return Attribute.DefaultUsageAttribute;
 463
 464			AttributeUsageAttribute aua = null;
 465			var type = this;
 466			while (type != null) {
 467				aua = type.MemberDefinition.GetAttributeUsage (pa);
 468				if (aua != null)
 469					break;
 470
 471				type = type.BaseType;
 472			}
 473
 474			return aua;
 475		}
 476
 477		//
 478		// Return metadata information used during emit to describe the type
 479		//
 480		public virtual MetaType GetMetaInfo ()
 481		{
 482			return info;
 483		}
 484
 485		public virtual TypeSpec GetDefinition ()
 486		{
 487			return this;
 488		}
 489
 490		//
 491		// Text representation of type used by documentation writer
 492		//
 493		public override string GetSignatureForDocumentation ()
 494		{
 495			StringBuilder sb = new StringBuilder ();
 496			if (IsNested) {
 497				sb.Append (DeclaringType.GetSignatureForDocumentation ());
 498			} else {
 499				sb.Append (MemberDefinition.Namespace);
 500			}
 501
 502			if (sb.Length != 0)
 503				sb.Append (".");
 504
 505			sb.Append (Name);
 506			if (Arity > 0) {
 507				if (this is InflatedTypeSpec) {
 508				    sb.Append ("{");
 509				    for (int i = 0; i < Arity; ++i) {
 510				        if (i > 0)
 511				            sb.Append (",");
 512
 513				        sb.Append (TypeArguments[i].GetSignatureForDocumentation ());
 514				    }
 515				    sb.Append ("}");
 516				} else {
 517					sb.Append ("`");
 518					sb.Append (Arity.ToString ());
 519				}
 520			}
 521
 522			return sb.ToString ();
 523		}
 524
 525		public string GetExplicitNameSignatureForDocumentation ()
 526		{
 527			StringBuilder sb = new StringBuilder ();
 528			if (IsNested) {
 529				sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ());
 530			} else if (MemberDefinition.Namespace != null) {
 531				sb.Append (MemberDefinition.Namespace.Replace ('.', '#'));
 532			}
 533
 534			if (sb.Length != 0)
 535				sb.Append ("#");
 536
 537			sb.Append (Name);
 538			if (Arity > 0) {
 539				sb.Append ("{");
 540				for (int i = 0; i < Arity; ++i) {
 541					if (i > 0)
 542						sb.Append (",");
 543
 544					sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ());
 545				}
 546				sb.Append ("}");
 547			}
 548
 549			return sb.ToString ();
 550		}
 551
 552		public override string GetSignatureForError ()
 553		{
 554			string s;
 555
 556			if (IsNested) {
 557				s = DeclaringType.GetSignatureForError ();
 558			} else if (MemberDefinition is AnonymousTypeClass) {
 559				return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
 560			} else {
 561				s = MemberDefinition.Namespace;
 562			}
 563
 564			if (!string.IsNullOrEmpty (s))
 565				s += ".";
 566
 567			return s + Name + GetTypeNameSignature ();
 568		}
 569
 570		public string GetSignatureForErrorIncludingAssemblyName ()
 571		{
 572			return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName);
 573		}
 574
 575		protected virtual string GetTypeNameSignature ()
 576		{
 577			if (!IsGeneric)
 578				return null;
 579
 580			return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
 581		}
 582
 583		public bool ImplementsInterface (TypeSpec iface, bool variantly)
 584		{
 585			var ifaces = Interfaces;
 586			if (ifaces != null) {
 587				for (int i = 0; i < ifaces.Count; ++i) {
 588					if (TypeSpecComparer.IsEqual (ifaces[i], iface))
 589						return true;
 590
 591					if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface))
 592						return true;
 593				}
 594			}
 595
 596			return false;
 597		}
 598
 599		protected virtual void InitializeMemberCache (bool onlyTypes)
 600		{
 601			try {
 602				MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
 603			} catch (Exception e) {
 604				throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ());
 605			}
 606
 607			if (onlyTypes)
 608				state |= StateFlags.PendingMemberCacheMembers;
 609			else
 610				state &= ~StateFlags.PendingMemberCacheMembers;
 611		}
 612
 613		//
 614		// Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
 615		// comparison is used to hide differences between `object' and `dynamic' for generic
 616		// types. Should not be used for comparisons where G<object> != G<dynamic>
 617		//
 618		public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
 619		{
 620			if (dynamicIsObject && baseClass.IsGeneric) {
 621				//
 622				// Returns true for a hierarchies like this when passing baseClass of A<dynamic>
 623				//
 624				// class B : A<object> {}
 625				//
 626				type = type.BaseType;
 627				while (type != null) {
 628					if (TypeSpecComparer.IsEqual (type, baseClass))
 629						return true;
 630
 631					type = type.BaseType;
 632				}
 633
 634				return false;
 635			}
 636
 637			while (type != null) {
 638				type = type.BaseType;
 639				if (type == baseClass)
 640					return true;
 641			}
 642
 643			return false;
 644		}
 645
 646		public static bool IsReferenceType (TypeSpec t)
 647		{
 648			switch (t.Kind) {
 649			case MemberKind.TypeParameter:
 650				return ((TypeParameterSpec) t).IsReferenceType;
 651			case MemberKind.Struct:
 652			case MemberKind.Enum:
 653			case MemberKind.Void:
 654			case MemberKind.PointerType:
 655				return false;
 656			case MemberKind.InternalCompilerType:
 657				//
 658				// Null is considered to be a reference type
 659				//			
 660				return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
 661			default:
 662				return true;
 663			}
 664		}
 665
 666		public static bool IsNonNullableValueType (TypeSpec t)
 667		{
 668			switch (t.Kind) {
 669			case MemberKind.TypeParameter:
 670				return ((TypeParameterSpec) t).IsValueType;
 671			case MemberKind.Struct:
 672				return !t.IsNullableType;
 673			case MemberKind.Enum:
 674				return true;
 675			default:
 676				return false;
 677			}
 678		}
 679
 680		public static bool IsValueType (TypeSpec t)
 681		{
 682			switch (t.Kind) {
 683			case MemberKind.TypeParameter:
 684				return ((TypeParameterSpec) t).IsValueType;
 685			case MemberKind.Struct:
 686			case MemberKind.Enum:
 687				return true;
 688			default:
 689				return false;
 690			}
 691		}
 692
 693		public override MemberSpec InflateMember (TypeParameterInflator inflator)
 694		{
 695			var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
 696
 697			//
 698			// When inflating nested type from inside the type instance will be same
 699			// because type parameters are same for all nested types
 700			//
 701			if (DeclaringType == inflator.TypeInstance) {
 702				return MakeGenericType (inflator.Context, targs);
 703			}
 704
 705			return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs);
 706		}
 707
 708		//
 709		// Inflates current type using specific type arguments
 710		//
 711		public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs)
 712		{
 713			if (targs.Length == 0 && !IsNested)
 714				throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
 715
 716			InflatedTypeSpec instance;
 717
 718			if (inflated_instances == null) {
 719				inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
 720
 721				if (IsNested) {
 722					instance = this as InflatedTypeSpec;
 723					if (instance != null) {
 724						//
 725						// Nested types could be inflated on already inflated instances
 726						// Caching this type ensured we are using same instance for
 727						// inside/outside inflation using local type parameters
 728						//
 729						inflated_instances.Add (TypeArguments, instance);
 730					}
 731				}
 732			}
 733
 734			if (!inflated_instances.TryGetValue (targs, out instance)) {
 735				if (GetDefinition () != this && !IsNested)
 736					throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
 737						GetSignatureForError ());
 738
 739				instance = new InflatedTypeSpec (context, this, declaringType, targs);
 740				inflated_instances.Add (targs, instance);
 741			}
 742
 743			return instance;
 744		}
 745
 746		public virtual TypeSpec Mutate (TypeParameterMutator mutator)
 747		{
 748			return this;
 749		}
 750
 751		public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
 752		{
 753			List<MissingTypeSpecReference> missing = null;
 754
 755			if (Kind == MemberKind.MissingType) {
 756				missing = new List<MissingTypeSpecReference> ();
 757				missing.Add (new MissingTypeSpecReference (this, caller));
 758				return missing;
 759			}
 760
 761			foreach (var targ in TypeArguments) {
 762				if (targ.Kind == MemberKind.MissingType) {
 763					if (missing == null)
 764						missing = new List<MissingTypeSpecReference> ();
 765
 766					missing.Add (new MissingTypeSpecReference (targ, caller));
 767				}
 768			}
 769
 770			if (Interfaces != null) {
 771				foreach (var iface in Interfaces) {
 772					if (iface.Kind == MemberKind.MissingType) {
 773						if (missing == null)
 774							missing = new List<MissingTypeSpecReference> ();
 775
 776						missing.Add (new MissingTypeSpecReference (iface, caller));
 777					}
 778				}
 779			}
 780
 781			if (MemberDefinition.TypeParametersCount > 0) {
 782				foreach (var tp in MemberDefinition.TypeParameters) {
 783					var tp_missing = tp.GetMissingDependencies (this);
 784					if (tp_missing != null) {
 785						if (missing == null)
 786							missing = new List<MissingTypeSpecReference> ();
 787
 788						missing.AddRange (tp_missing);
 789					}
 790				}
 791			}
 792
 793			if (missing != null || BaseType == null)
 794				return missing;
 795
 796			return BaseType.ResolveMissingDependencies (this);
 797		}
 798
 799		public void SetMetaInfo (MetaType info)
 800		{
 801			if (this.info != null)
 802				throw new InternalErrorException ("MetaInfo reset");
 803
 804			this.info = info;
 805		}
 806
 807		public void SetExtensionMethodContainer ()
 808		{
 809			modifiers |= Modifiers.METHOD_EXTENSION;
 810		}
 811
 812		public void UpdateInflatedInstancesBaseType ()
 813		{
 814			//
 815			// When nested class has a partial part the situation where parent type
 816			// is inflated before its base type is defined can occur. In such case
 817			// all inflated (should be only 1) instansted need to be updated
 818			//
 819			// partial class A<T> {
 820			//   partial class B : A<int> { }
 821			// }
 822			//
 823			// partial class A<T> : X {}
 824			//
 825			if (inflated_instances == null)
 826				return;
 827
 828			foreach (var inflated in inflated_instances) {
 829				//
 830				// Don't need to inflate possible generic type because for now the method
 831				// is always used from within the nested type
 832				//
 833				inflated.Value.BaseType = base_type;
 834			}
 835		}
 836	}
 837
 838	//
 839	// Special version used for types which must exist in corlib or
 840	// the compiler cannot work
 841	//
 842	public sealed class BuiltinTypeSpec : TypeSpec
 843	{
 844		public enum Type
 845		{
 846			None = 0,
 847
 848			// Ordered carefully for fast compares
 849			FirstPrimitive = 1,
 850			Bool = 1,
 851			Byte = 2,
 852			SByte = 3,
 853			Char = 4,
 854			Short = 5,
 855			UShort = 6,
 856			Int = 7,
 857			UInt = 8,
 858			Long = 9,
 859			ULong = 10,
 860			Float = 11,
 861			Double = 12,
 862			LastPrimitive = 12,
 863			Decimal = 13,
 864
 865			IntPtr = 14,
 866			UIntPtr = 15,
 867
 868			Object = 16,
 869			Dynamic = 17,
 870			String = 18,
 871			Type = 19,
 872
 873			ValueType = 20,
 874			Enum = 21,
 875			Delegate = 22,
 876			MulticastDelegate = 23,
 877			Array = 24,
 878
 879			IEnumerator,
 880			IEnumerable,
 881			IDisposable,
 882			Exception,
 883			Attribute,
 884			Other,
 885		}
 886
 887		readonly Type type;
 888		readonly string ns;
 889		readonly string name;
 890
 891		public BuiltinTypeSpec (MemberKind kind, string ns, string name, Type builtinKind)
 892			: base (kind, null, null, null, Modifiers.PUBLIC)
 893		{
 894			this.type = builtinKind;
 895			this.ns = ns;
 896			this.name = name;
 897		}
 898
 899		public BuiltinTypeSpec (string name, Type builtinKind)
 900			: this (MemberKind.InternalCompilerType, "", name, builtinKind)
 901		{
 902			// Make all internal types CLS-compliant, non-obsolete, compact
 903			state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
 904		}
 905
 906		#region Properties
 907
 908		public override int Arity {
 909			get {
 910				return 0;
 911			}
 912		}
 913
 914		public override BuiltinTypeSpec.Type BuiltinType {
 915			get {
 916				return type;
 917			}
 918		}
 919
 920		public string FullName {
 921			get {
 922				return ns + '.' + name;
 923			}
 924		}
 925
 926		public override string Name {
 927			get {
 928				return name;
 929			}
 930		}
 931
 932		public string Namespace {
 933			get {
 934				return ns;
 935			}
 936		}
 937
 938		#endregion
 939
 940		public static bool IsPrimitiveType (TypeSpec type)
 941		{
 942			return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.LastPrimitive;
 943		}
 944
 945		public static bool IsPrimitiveTypeOrDecimal (TypeSpec type)
 946		{
 947			return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.Decimal;
 948		}
 949
 950		public override string GetSignatureForError ()
 951		{
 952			switch (Name) {
 953			case "Int32": return "int";
 954			case "Int64": return "long";
 955			case "String": return "string";
 956			case "Boolean": return "bool";
 957			case "Void": return "void";
 958			case "Object": return "object";
 959			case "UInt32": return "uint";
 960			case "Int16": return "short";
 961			case "UInt16": return "ushort";
 962			case "UInt64": return "ulong";
 963			case "Single": return "float";
 964			case "Double": return "double";
 965			case "Decimal": return "decimal";
 966			case "Char": return "char";
 967			case "Byte": return "byte";
 968			case "SByte": return "sbyte";
 969			}
 970
 971			if (ns.Length == 0)
 972				return name;
 973
 974			return FullName;
 975		}
 976
 977		//
 978		// Returns the size of type if known, otherwise, 0
 979		//
 980		public static int GetSize (TypeSpec type)
 981		{
 982			switch (type.BuiltinType) {
 983			case Type.Int:
 984			case Type.UInt:
 985			case Type.Float:
 986				return 4;
 987			case Type.Long:
 988			case Type.ULong:
 989			case Type.Double:
 990				return 8;
 991			case Type.Byte:
 992			case Type.SByte:
 993			case Type.Bool:
 994				return 1;
 995			case Type.Short:
 996			case Type.Char:
 997			case Type.UShort:
 998				return 2;
 999			case Type.Decimal:
1000				return 16;
1001			default:
1002				return 0;
1003			}
1004		}
1005
1006		public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod)
1007		{
1008			this.definition = td;
1009			this.info = type;
1010			this.modifiers |= (mod & ~Modifiers.AccessibilityMask);
1011		}
1012
1013		public void SetDefinition (TypeSpec ts)
1014		{
1015			this.definition = ts.MemberDefinition;
1016			this.info = ts.GetMetaInfo ();
1017			this.BaseType = ts.BaseType;
1018			this.Interfaces = ts.Interfaces;
1019			this.modifiers = ts.Modifiers;
1020		}
1021	}
1022
1023	//
1024	// Various type comparers used by compiler
1025	//
1026	static class TypeSpecComparer
1027	{
1028		//
1029		// Does strict reference comparion only
1030		//
1031		public static readonly DefaultImpl Default = new DefaultImpl ();
1032
1033		public class DefaultImpl : IEqualityComparer<TypeSpec[]>
1034		{
1035			#region IEqualityComparer<TypeSpec[]> Members
1036
1037			bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
1038			{
1039				if (x == y)
1040					return true;
1041
1042				if (x.Length != y.Length)
1043					return false;
1044
1045				for (int i = 0; i < x.Length; ++i)
1046					if (x[i] != y[i])
1047						return false;
1048
1049				return true;
1050			}
1051
1052			int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
1053			{
1054				int hash = 0;
1055				for (int i = 0; i < obj.Length; ++i)
1056					hash = (hash << 5) - hash + obj[i].GetHashCode ();
1057
1058				return hash;
1059			}
1060
1061			#endregion
1062		}
1063
1064		//
1065		// When comparing type signature of overrides or overloads
1066		// this version tolerates different MVARs at same position
1067		//
1068		public static class Override
1069		{
1070			public static bool IsEqual (TypeSpec a, TypeSpec b)
1071			{
1072				if (a == b)
1073					return true;
1074
1075				//
1076				// Consider the following example:
1077				//
1078				//     public abstract class A
1079				//     {
1080				//        public abstract T Foo<T>();
1081				//     }
1082				//
1083				//     public class B : A
1084				//     {
1085				//        public override U Foo<T>() { return default (U); }
1086				//     }
1087				//
1088				// Here, `T' and `U' are method type parameters from different methods
1089				// (A.Foo and B.Foo), so both `==' and Equals() will fail.
1090				//
1091				// However, since we're determining whether B.Foo() overrides A.Foo(),
1092				// we need to do a signature based comparision and consider them equal.
1093				//
1094
1095				var tp_a = a as TypeParameterSpec;
1096				if (tp_a != null) {
1097					var tp_b = b as TypeParameterSpec;
1098					return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
1099				}
1100
1101				var ac_a = a as ArrayContainer;
1102				if (ac_a != null) {
1103					var ac_b = b as ArrayContainer;
1104					return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
1105				}
1106
1107				if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1108					return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
1109
1110				if (a.MemberDefinition != b.MemberDefinition)
1111					return false;
1112
1113				do {
1114					for (int i = 0; i < a.TypeArguments.Length; ++i) {
1115						if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
1116							return false;
1117					}
1118
1119					a = a.DeclaringType;
1120					b = b.DeclaringType;
1121				} while (a != null);
1122
1123				return true;
1124			}
1125
1126			public static bool IsEqual (TypeSpec[] a, TypeSpec[] b)
1127			{
1128				if (a == b)
1129					return true;
1130
1131				if (a.Length != b.Length)
1132					return false;
1133
1134				for (int i = 0; i < a.Length; ++i) {
1135					if (!IsEqual (a[i], b[i]))
1136						return false;
1137				}
1138
1139				return true;
1140			}
1141
1142
1143			//
1144			// Compares unordered arrays
1145			//
1146			public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
1147			{
1148				if (a == b)
1149					return true;
1150
1151				if (a == null || b == null || a.Length != b.Length)
1152					return false;
1153
1154				for (int ai = 0; ai < a.Length; ++ai) {
1155					bool found = false;
1156					for (int bi = 0; bi < b.Length; ++bi) {
1157						if (IsEqual (a[ai], b[bi])) {
1158							found = true;
1159							break;
1160						}
1161					}
1162
1163					if (!found)
1164						return false;
1165				}
1166
1167				return true;
1168			}
1169
1170			public static bool IsEqual (AParametersCollection a, AParametersCollection b)
1171			{
1172				if (a == b)
1173					return true;
1174
1175				if (a.Count != b.Count)
1176					return false;
1177
1178				for (int i = 0; i < a.Count; ++i) {
1179					if (!IsEqual (a.Types[i], b.Types[i]))
1180						return false;
1181
1182					if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
1183						return false;
1184				}
1185
1186				return true;
1187			}
1188		}
1189
1190		//
1191		// Type variance equality comparison
1192		//
1193		public static class Variant
1194		{
1195			public static bool IsEqual (TypeSpec type1, TypeSpec type2)
1196			{
1197				if (!type1.IsGeneric || !type2.IsGeneric)
1198					return false;
1199
1200				var target_type_def = type2.MemberDefinition;
1201				if (type1.MemberDefinition != target_type_def)
1202					return false;
1203
1204				var t1_targs = type1.TypeArguments;
1205				var t2_targs = type2.TypeArguments;
1206				var targs_definition = target_type_def.TypeParameters;
1207
1208				if (!type1.IsInterface && !type1.IsDelegate) {
1209					return false;
1210				}
1211
1212				for (int i = 0; i < targs_definition.Length; ++i) {
1213					if (TypeSpecComparer.IsEqual (t1_targs[i], t2_targs[i]))
1214						continue;
1215
1216					Variance v = targs_definition[i].Variance;
1217					if (v == Variance.None) {
1218						return false;
1219					}
1220
1221					if (v == Variance.Covariant) {
1222						if (!Convert.ImplicitReferenceConversionExists (t1_targs[i], t2_targs[i]))
1223							return false;
1224					} else if (!Convert.ImplicitReferenceConversionExists (t2_targs[i], t1_targs[i])) {
1225						return false;
1226					}
1227				}
1228
1229				return true;
1230			}
1231		}
1232
1233		//
1234		// Checks whether two generic instances may become equal for some
1235		// particular instantiation (26.3.1).
1236		//
1237		public static class Unify
1238		{
1239			//
1240			// Either @a or @b must be generic type
1241			//
1242			public static bool IsEqual (TypeSpec a, TypeSpec b)
1243			{
1244				if (a.MemberDefinition != b.MemberDefinition) {
1245					var base_ifaces = a.Interfaces;
1246					if (base_ifaces != null) {
1247						foreach (var base_iface in base_ifaces) {
1248							if (base_iface.Arity > 0 && IsEqual (base_iface, b))
1249								return true;
1250						}
1251					}
1252
1253					return false;
1254				}
1255
1256				var ta = a.TypeArguments;
1257				var tb = b.TypeArguments;
1258				for (int i = 0; i < ta.Length; i++) {
1259					if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
1260						return false;
1261				}
1262
1263				if (a.IsNested && b.IsNested)
1264					return IsEqual (a.DeclaringType, b.DeclaringType);
1265
1266				return true;
1267			}
1268
1269			static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
1270			{
1271				TypeSpec[] targs = type.TypeArguments;
1272				for (int i = 0; i < targs.Length; i++) {
1273					if (tparam == targs[i])
1274						return true;
1275
1276					if (ContainsTypeParameter (tparam, targs[i]))
1277						return true;
1278				}
1279
1280				return false;
1281			}
1282
1283			/// <summary>
1284			///   Check whether `a' and `b' may become equal generic types.
1285			///   The algorithm to do that is a little bit complicated.
1286			/// </summary>
1287			static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
1288			{
1289				if (a.IsGenericParameter) {
1290					//
1291					// If a is an array of a's type, they may never
1292					// become equal.
1293					//
1294					if (b.IsArray)
1295						return false;
1296
1297					//
1298					// If b is a generic parameter or an actual type,
1299					// they may become equal:
1300					//
1301					//    class X<T,U> : I<T>, I<U>
1302					//    class X<T> : I<T>, I<float>
1303					// 
1304					if (b.IsGenericParameter)
1305						return a != b && a.DeclaringType == b.DeclaringType;
1306
1307					//
1308					// We're now comparing a type parameter with a
1309					// generic instance.  They may become equal unless
1310					// the type parameter appears anywhere in the
1311					// generic instance:
1312					//
1313					//    class X<T,U> : I<T>, I<X<U>>
1314					//        -> error because you could instanciate it as
1315					//           X<X<int>,int>
1316					//
1317					//    class X<T> : I<T>, I<X<T>> -> ok
1318					//
1319
1320					return !ContainsTypeParameter (a, b);
1321				}
1322
1323				if (b.IsGenericParameter)
1324					return MayBecomeEqualGenericTypes (b, a);
1325
1326				//
1327				// At this point, neither a nor b are a type parameter.
1328				//
1329				// If one of them is a generic instance, compare them (if the
1330				// other one is not a generic instance, they can never
1331				// become equal).
1332				//
1333				if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
1334					return IsEqual (a, b);
1335
1336				//
1337				// If both of them are arrays.
1338				//
1339				var a_ac = a as ArrayContainer;
1340				if (a_ac != null) {
1341					var b_ac = b as ArrayContainer;
1342					if (b_ac == null || a_ac.Rank != b_ac.Rank)
1343						return false;
1344
1345					return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
1346				}
1347
1348				//
1349				// Ok, two ordinary types.
1350				//
1351				return false;
1352			}
1353		}
1354
1355		public static bool Equals (TypeSpec[] x, TypeSpec[] y)
1356		{
1357			if (x == y)
1358				return true;
1359
1360			if (x.Length != y.Length)
1361				return false;
1362
1363			for (int i = 0; i < x.Length; ++i)
1364				if (!IsEqual (x[i], y[i]))
1365					return false;
1366
1367			return true;
1368		}
1369
1370		//
1371		// Identity type conversion
1372		//
1373		// Default reference comparison, it has to be used when comparing
1374		// two possible dynamic/internal types
1375		//
1376		public static bool IsEqual (TypeSpec a, TypeSpec b)
1377		{
1378			if (a == b) {
1379				// This also rejects dynamic == dynamic
1380				return a.Kind != MemberKind.InternalCompilerType || a.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
1381			}
1382
1383			if (a == null || b == null)
1384				return false;
1385
1386			if (a.IsArray) {
1387				var a_a = (ArrayContainer) a;
1388				var b_a = b as ArrayContainer;
1389				if (b_a == null)
1390					return false;
1391
1392				return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element);
1393			}
1394
1395			if (!a.IsGeneric || !b.IsGeneric) {
1396				//
1397				// object and dynamic are considered equivalent there is an identity conversion
1398				// between object and dynamic, and between constructed types that are the same
1399				// when replacing all occurences of dynamic with object.
1400				//
1401				if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1402					return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
1403
1404				return false;
1405			}
1406
1407			if (a.MemberDefinition != b.MemberDefinition)
1408				return false;
1409
1410			do {
1411				if (!Equals (a.TypeArguments, b.TypeArguments))
1412					return false;
1413
1414				a = a.DeclaringType;
1415				b = b.DeclaringType;
1416			} while (a != null);
1417
1418			return true;
1419		}
1420	}
1421
1422	public interface ITypeDefinition : IMemberDefinition
1423	{
1424		IAssemblyDefinition DeclaringAssembly { get; }
1425		string Namespace { get; }
1426		bool IsPartial { get; }
1427		bool IsComImport { get; }
1428		bool IsTypeForwarder { get; }
1429		bool IsCyclicTypeForwarder { get; }
1430		int TypeParametersCount { get; }
1431		TypeParameterSpec[] TypeParameters { get; }
1432
1433		TypeSpec GetAttributeCoClass ();
1434		string GetAttributeDefaultMember ();
1435		AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
1436		bool IsInternalAsPublic (IAssemblyDefinition assembly);
1437		void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
1438	}
1439
1440	class InternalType : TypeSpec, ITypeDefinition
1441	{
1442		public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
1443		public static readonly InternalType Arglist = new InternalType ("__arglist");
1444		public static readonly InternalType MethodGroup = new InternalType ("method group");
1445		public static readonly InternalType NullLiteral = new InternalType ("null");
1446		public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
1447		public static readonly InternalType Namespace = new InternalType ("<namespace>");
1448		public static readonly InternalType ErrorType = new InternalType ("<error>");
1449
1450		readonly string name;
1451
1452		InternalType (string name)
1453			: base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
1454		{
1455			this.name = name;
1456			this.definition = this;
1457			cache = MemberCache.Empty;
1458
1459			// Make all internal types CLS-compliant, non-obsolete
1460			state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
1461		}
1462
1463		#region Properties
1464
1465		public override int Arity {
1466			get {
1467				return 0;
1468			}
1469		}
1470
1471		IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1472			get {
1473				throw new NotImplementedException ();
1474			}
1475		}
1476
1477		bool ITypeDefinition.IsComImport {
1478			get {
1479				return false;
1480			}
1481		}
1482
1483		bool IMemberDefinition.IsImported {
1484			get {
1485				return false;
1486			}
1487		}
1488
1489		bool ITypeDefinition.IsPartial {
1490			get {
1491				return false;
1492			}
1493		}
1494
1495		bool ITypeDefinition.IsTypeForwarder {
1496			get {
1497				return false;
1498			}
1499		}
1500
1501		bool ITypeDefinition.IsCyclicTypeForwarder {
1502			get {
1503				return false;
1504			}
1505		}
1506
1507		public override string Name {
1508			get {
1509				return name;
1510			}
1511		}
1512
1513		string ITypeDefinition.Namespace {
1514			get {
1515				return null;
1516			}
1517		}
1518
1519		int ITypeDefinition.TypeParametersCount {
1520			get {
1521				return 0;
1522			}
1523		}
1524
1525		TypeParameterSpec[] ITypeDefinition.TypeParameters {
1526			get {
1527				return null;
1528			}
1529		}
1530
1531		#endregion
1532
1533		public override string GetSignatureForError ()
1534		{
1535			return name;
1536		}
1537
1538		#region ITypeDefinition Members
1539
1540		TypeSpec ITypeDefinition.GetAttributeCoClass ()
1541		{
1542			return null;
1543		}
1544
1545		string ITypeDefinition.GetAttributeDefaultMember ()
1546		{
1547			return null;
1548		}
1549
1550		AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
1551		{
1552			return null;
1553		}
1554
1555		bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1556		{
1557			throw new NotImplementedException ();
1558		}
1559
1560		void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1561		{
1562			throw new NotImplementedException ();
1563		}
1564
1565		string[] IMemberDefinition.ConditionalConditions ()
1566		{
1567			return null;
1568		}
1569
1570		ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
1571		{
1572			return null;
1573		}
1574
1575		bool? IMemberDefinition.CLSAttributeValue {
1576			get {
1577				return null;
1578			}
1579		}
1580
1581		void IMemberDefinition.SetIsAssigned ()
1582		{
1583		}
1584
1585		void IMemberDefinition.SetIsUsed ()
1586		{
1587		}
1588
1589		#endregion
1590	}
1591
1592	//
1593	// Common base class for composite types
1594	//
1595	public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1596	{
1597		protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info)
1598			: base (kind, element.DeclaringType, null, info, element.Modifiers)
1599		{
1600			this.Element = element;
1601
1602			state &= ~SharedStateFlags;
1603			state |= (element.state & SharedStateFlags);
1604
1605			if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1606				state |= StateFlags.HasDynamicElement;
1607
1608			// Has to use its own type definition instead of just element definition to
1609			// correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1610			this.definition = this;
1611
1612			cache = MemberCache.Empty;
1613		}
1614
1615		#region Properties
1616
1617		public TypeSpec Element { get; private set; }
1618
1619		bool ITypeDefinition.IsComImport {
1620			get {
1621				return false;
1622			}
1623		}
1624
1625		bool ITypeDefinition.IsPartial {
1626			get {
1627				return false;
1628			}
1629		}
1630
1631		bool ITypeDefinition.IsTypeForwarder {
1632			get {
1633				return false;
1634			}
1635		}
1636
1637		bool ITypeDefinition.IsCyclicTypeForwarder {
1638			get {
1639				return false;
1640			}
1641		}
1642
1643		public override string Name {
1644			get {
1645				throw new NotSupportedException ();
1646			}
1647		}
1648
1649		#endregion
1650
1651		public override ObsoleteAttribute GetAttributeObsolete ()
1652		{
1653			return Element.GetAttributeObsolete ();
1654		}
1655
1656		protected virtual string GetPostfixSignature ()
1657		{
1658			return null;
1659		}
1660
1661		public override string GetSignatureForDocumentation ()
1662		{
1663			return Element.GetSignatureForDocumentation () + GetPostfixSignature ();
1664		}
1665
1666		public override string GetSignatureForError ()
1667		{
1668			return Element.GetSignatureForError () + GetPostfixSignature ();
1669		}
1670
1671		public override TypeSpec Mutate (TypeParameterMutator mutator)
1672		{
1673			var me = Element.Mutate (mutator);
1674			if (me == Element)
1675				return this;
1676
1677			var mutated = (ElementTypeSpec) MemberwiseClone ();
1678			mutated.Element = me;
1679			mutated.info = null;
1680			return mutated;
1681		}
1682
1683		#region ITypeDefinition Members
1684
1685		IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1686			get {
1687				return Element.MemberDefinition.DeclaringAssembly;
1688			}
1689		}
1690
1691		bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1692		{
1693			return Element.MemberDefinition.IsInternalAsPublic (assembly);
1694		}
1695
1696		public string Namespace {
1697			get { throw new NotImplementedException (); }
1698		}
1699
1700		public int TypeParametersCount {
1701			get {
1702				return 0;
1703			}
1704		}
1705
1706		public TypeParameterSpec[] TypeParameters {
1707			get {
1708				throw new NotSupportedException ();
1709			}
1710		}
1711
1712		public TypeSpec GetAttributeCoClass ()
1713		{
1714			return Element.MemberDefinition.GetAttributeCoClass ();
1715		}
1716
1717		public string GetAttributeDefaultMember ()
1718		{
1719			return Element.MemberDefinition.GetAttributeDefaultMember ();
1720		}
1721
1722		public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1723		{
1724			Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1725		}
1726
1727		public bool IsImported {
1728			get {
1729				return Element.MemberDefinition.IsImported;
1730			}
1731		}
1732
1733		public string[] ConditionalConditions ()
1734		{
1735			return Element.MemberDefinition.ConditionalConditions ();
1736		}
1737
1738		bool? IMemberDefinition.CLSAttributeValue {
1739			get {
1740				return Element.MemberDefinition.CLSAttributeValue;
1741			}
1742		}
1743
1744		public void SetIsAssigned ()
1745		{
1746			Element.MemberDefinition.SetIsAssigned ();
1747		}
1748
1749		public void SetIsUsed ()
1750		{
1751			Element.MemberDefinition.SetIsUsed ();
1752		}
1753
1754		#endregion
1755	}
1756
1757	public class ArrayContainer : ElementTypeSpec
1758	{
1759		public struct TypeRankPair : IEquatable<TypeRankPair>
1760		{
1761			TypeSpec ts;
1762			int rank;
1763
1764			public TypeRankPair (TypeSpec ts, int rank)
1765			{
1766				this.ts = ts;
1767				this.rank = rank;
1768			}
1769
1770			public override int GetHashCode ()
1771			{
1772				return ts.GetHashCode () ^ rank.GetHashCode ();
1773			}
1774
1775			#region IEquatable<Tuple<T1,T2>> Members
1776
1777			public bool Equals (TypeRankPair other)
1778			{
1779				return other.ts == ts && other.rank == rank;
1780			}
1781
1782			#endregion
1783		}
1784
1785		readonly int rank;
1786		readonly ModuleContainer module;
1787
1788		private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
1789			: base (MemberKind.ArrayType, element, null)
1790		{
1791			this.module = module;
1792			this.rank = rank;
1793		}
1794
1795		public int Rank {
1796			get {
1797				return rank;
1798			}
1799		}
1800
1801		public MethodInfo GetConstructor ()
1802		{
1803			var mb = module.Builder;
1804
1805			var arg_types = new MetaType[rank];
1806			for (int i = 0; i < rank; i++)
1807				arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1808
1809			var ctor = mb.GetArrayMethod (
1810				GetMetaInfo (), Constructor.ConstructorName,
1811				CallingConventions.HasThis,
1812				null, arg_types);
1813
1814			return ctor;
1815		}
1816
1817		public MethodInfo GetAddressMethod ()
1818		{
1819			var mb = module.Builder;
1820
1821			var arg_types = new MetaType[rank];
1822			for (int i = 0; i < rank; i++)
1823				arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1824
1825			var address = mb.GetArrayMethod (
1826				GetMetaInfo (), "Address",
1827				CallingConventions.HasThis | CallingConventions.Standard,
1828				ReferenceContainer.MakeType (module, Element).GetMetaInfo (), arg_types);
1829
1830			return address;
1831		}
1832
1833		public MethodInfo GetGetMethod ()
1834		{
1835			var mb = module.Builder;
1836
1837			var arg_types = new MetaType[rank];
1838			for (int i = 0; i < rank; i++)
1839				arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1840
1841			var get = mb.GetArrayMethod (
1842				GetMetaInfo (), "Get",
1843				CallingConventions.HasThis | CallingConventions.Standard,
1844				Element.GetMetaInfo (), arg_types);
1845
1846			return get;
1847		}
1848
1849		public MethodInfo GetSetMethod ()
1850		{
1851			var mb = module.Builder;
1852
1853			var arg_types = new MetaType[rank + 1];
1854			for (int i = 0; i < rank; i++)
1855				arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1856
1857			arg_types[rank] = Element.GetMetaInfo ();
1858
1859			var set = mb.GetArrayMethod (
1860				GetMetaInfo (), "Set",
1861				CallingConventions.HasThis | CallingConventions.Standard,
1862				module.Compiler.BuiltinTypes.Void.GetMetaInfo (), arg_types);
1863
1864			return set;
1865		}
1866
1867		public override MetaType GetMetaInfo ()
1868		{
1869			if (info == null) {
1870				if (rank == 1)
1871					info = Element.GetMetaInfo ().MakeArrayType ();
1872				else
1873					info = Element.GetMetaInfo ().MakeArrayType (rank);
1874			}
1875
1876			return info;
1877		}
1878
1879		protected override string GetPostfixSignature()
1880		{
1881			return GetPostfixSignature (rank);
1882		}
1883
1884		public static string GetPostfixSignature (int rank)
1885		{
1886			StringBuilder sb = new StringBuilder ();
1887			sb.Append ("[");
1888			for (int i = 1; i < rank; i++) {
1889				sb.Append (",");
1890			}
1891			sb.Append ("]");
1892
1893			return sb.ToString ();
1894		}
1895
1896		public override string GetSignatureForDocumentation ()
1897		{
1898			StringBuilder sb = new StringBuilder ();
1899			GetElementSignatureForDocumentation (sb);
1900			return sb.ToString ();
1901		}
1902
1903		void GetElementSignatureForDocumentation (StringBuilder sb)
1904		{
1905			var ac = Element as ArrayContainer;
1906			if (ac == null)
1907				sb.Append (Element.GetSignatureForDocumentation ());
1908			else
1909				ac.GetElementSignatureForDocumentation (sb);
1910
1911			sb.Append ("[");
1912			for (int i = 1; i < rank; i++) {
1913				if (i == 1)
1914					sb.Append ("0:");
1915
1916				sb.Append (",0:");
1917			}
1918			sb.Append ("]");
1919		}
1920
1921		public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)
1922		{
1923			return MakeType (module, element, 1);
1924		}
1925
1926		public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank)
1927		{
1928			ArrayContainer ac;
1929			var key = new TypeRankPair (element, rank);
1930			if (!module.ArrayTypesCache.TryGetValue (key, out ac)) {
1931				ac = new ArrayContainer (module, element, rank);
1932				ac.BaseType = module.Compiler.BuiltinTypes.Array;
1933				ac.Interfaces = ac.BaseType.Interfaces;
1934
1935				module.ArrayTypesCache.Add (key, ac);
1936			}
1937
1938			return ac;
1939		}
1940
1941		public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
1942		{
1943			return Element.ResolveMissingDependencies (caller);
1944		}
1945	}
1946
1947	class ReferenceContainer : ElementTypeSpec
1948	{
1949		private ReferenceContainer (TypeSpec element)
1950			: base (MemberKind.Class, element, null)	// TODO: Kind.Class is most likely wrong
1951		{
1952		}
1953
1954		public override MetaType GetMetaInfo ()
1955		{
1956			if (info == null) {
1957				info = Element.GetMetaInfo ().MakeByRefType ();
1958			}
1959
1960			return info;
1961		}
1962
1963		public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element)
1964		{
1965			ReferenceContainer pc;
1966			if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) {
1967				pc = new ReferenceContainer (element);
1968				module.ReferenceTypesCache.Add (element, pc);
1969			}
1970
1971			return pc;
1972		}
1973	}
1974
1975	class PointerContainer : ElementTypeSpec
1976	{
1977		private PointerContainer (TypeSpec element)
1978			: base (MemberKind.PointerType, element, null)
1979		{
1980			// It's never CLS-Compliant
1981			state &= ~StateFlags.CLSCompliant_Undetected;
1982		}
1983
1984		public override MetaType GetMetaInfo ()
1985		{
1986			if (info == null) {
1987				info = Element.GetMetaInfo ().MakePointerType ();
1988			}
1989
1990			return info;
1991		}
1992
1993		protected override string GetPostfixSignature()
1994		{
1995 			return "*";
1996		}
1997
1998		public static PointerContainer MakeType (ModuleContainer module, TypeSpec element)
1999		{
2000			PointerContainer pc;
2001			if (!module.PointerTypesCache.TryGetValue (element, out pc)) {
2002				pc = new PointerContainer (element);
2003				module.PointerTypesCache.Add (element, pc);
2004			}
2005
2006			return pc;
2007		}
2008	}
2009
2010	public class MissingTypeSpecReference
2011	{
2012		public MissingTypeSpecReference (TypeSpec type, MemberSpec caller)
2013		{
2014			Type = type;
2015			Caller = caller;
2016		}
2017
2018		public TypeSpec Type { get; private set; }
2019		public MemberSpec Caller { get; private set; }
2020	}
2021}