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