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