1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections.Generic; 7 using System.Diagnostics; 8 9 namespace Microsoft.CSharp.RuntimeBinder.Semantics 10 { 11 // ---------------------------------------------------------------------------- 12 // 13 // AggregateType 14 // 15 // Represents a generic constructed (or instantiated) type. Parent is the AggregateSymbol. 16 // ---------------------------------------------------------------------------- 17 18 internal sealed class AggregateType : CType 19 { 20 private TypeArray _pTypeArgsThis; 21 private TypeArray _pTypeArgsAll; // includes args from outer types 22 private AggregateSymbol _pOwningAggregate; 23 24 private AggregateType _baseType; // This is the result of calling SubstTypeArray on the aggregate's baseClass. 25 private TypeArray _ifacesAll; // This is the result of calling SubstTypeArray on the aggregate's ifacesAll. 26 private TypeArray _winrtifacesAll; //This is the list of collection interfaces implemented by a WinRT object. 27 28 public bool fConstraintsChecked; // Have the constraints been checked yet? 29 public bool fConstraintError; // Did the constraints check produce an error? 30 31 // These two flags are used to track hiding within interfaces. 32 // Their use and validity is always localized. See e.g. MemberLookup::LookupInInterfaces. 33 public bool fAllHidden; // All members are hidden by a derived interface member. 34 public bool fDiffHidden; // Members other than a specific kind are hidden by a derived interface member or class member. 35 36 public AggregateType outerType; // the outer type if this is a nested type 37 SetOwningAggregate(AggregateSymbol agg)38 public void SetOwningAggregate(AggregateSymbol agg) 39 { 40 _pOwningAggregate = agg; 41 } 42 GetOwningAggregate()43 public AggregateSymbol GetOwningAggregate() 44 { 45 return _pOwningAggregate; 46 } 47 GetBaseClass()48 public AggregateType GetBaseClass() 49 { 50 if (_baseType == null) 51 { 52 Type baseSysType = AssociatedSystemType.BaseType; 53 if (baseSysType == null) 54 { 55 return null; 56 } 57 58 // If we have a generic type definition, then we need to set the 59 // base class to be our current base type, and use that to calculate 60 // our agg type and its base, then set it to be the generic version of the 61 // base type. This is because: 62 // 63 // Suppose we have Foo<T> : IFoo<T> 64 // 65 // Initially, the BaseType will be IFoo<Foo.T>, which gives us the substitution 66 // that we want to use for our agg type's base type. However, in the Symbol chain, 67 // we want the base type to be IFoo<IFoo.T>. So we need to substitute. 68 // 69 // If we don't have a generic type definition, then we just need to set our base 70 // class. This is so that if we have a base type that's generic, we'll be 71 // getting the correctly instantiated base type. 72 TypeManager manager = GetOwningAggregate().GetTypeManager(); 73 AggregateType baseClass = manager.SymbolTable.GetCTypeFromType(baseSysType) as AggregateType; 74 Debug.Assert(baseClass != null); 75 _baseType = manager.SubstType(baseClass, GetTypeArgsAll()); 76 } 77 78 return _baseType; 79 } 80 81 public IEnumerable<AggregateType> TypeHierarchy 82 { 83 get 84 { 85 if (isInterfaceType()) 86 { 87 yield return this; 88 foreach (AggregateType iface in GetIfacesAll().Items) 89 { 90 yield return iface; 91 } 92 93 yield return getAggregate().GetTypeManager().ObjectAggregateType; 94 } 95 else 96 { 97 for (AggregateType agg = this; agg != null; agg = agg.GetBaseClass()) 98 { 99 yield return agg; 100 } 101 } 102 } 103 } 104 SetTypeArgsThis(TypeArray pTypeArgsThis)105 public void SetTypeArgsThis(TypeArray pTypeArgsThis) 106 { 107 TypeArray pOuterTypeArgs; 108 if (outerType != null) 109 { 110 Debug.Assert(outerType.GetTypeArgsThis() != null); 111 Debug.Assert(outerType.GetTypeArgsAll() != null); 112 113 pOuterTypeArgs = outerType.GetTypeArgsAll(); 114 } 115 else 116 { 117 pOuterTypeArgs = BSYMMGR.EmptyTypeArray(); 118 } 119 120 Debug.Assert(pTypeArgsThis != null); 121 _pTypeArgsThis = pTypeArgsThis; 122 SetTypeArgsAll(pOuterTypeArgs); 123 } 124 SetTypeArgsAll(TypeArray outerTypeArgs)125 private void SetTypeArgsAll(TypeArray outerTypeArgs) 126 { 127 Debug.Assert(_pTypeArgsThis != null); 128 129 // Here we need to check our current type args. If we have an open placeholder, 130 // then we need to have all open placeholders, and we want to flush 131 // our outer type args so that they're open placeholders. 132 // 133 // This is because of the following scenario: 134 // 135 // class B<T> 136 // { 137 // class C<U> 138 // { 139 // } 140 // class D 141 // { 142 // void Foo() 143 // { 144 // Type T = typeof(C<>); 145 // } 146 // } 147 // } 148 // 149 // The outer type will be B<T>, but the inner type will be C<>. However, 150 // this will eventually be represented in IL as B<>.C<>. As such, we should 151 // keep our data structures clear - if we have one open type argument, then 152 // all of them must be open type arguments. 153 // 154 // Ensure that invariant here. 155 156 TypeArray pCheckedOuterTypeArgs = outerTypeArgs; 157 TypeManager pTypeManager = getAggregate().GetTypeManager(); 158 _pTypeArgsAll = pTypeManager.ConcatenateTypeArrays(pCheckedOuterTypeArgs, _pTypeArgsThis); 159 } 160 GetTypeArgsThis()161 public TypeArray GetTypeArgsThis() 162 { 163 return _pTypeArgsThis; 164 } 165 GetTypeArgsAll()166 public TypeArray GetTypeArgsAll() 167 { 168 return _pTypeArgsAll; 169 } 170 GetIfacesAll()171 public TypeArray GetIfacesAll() 172 { 173 if (_ifacesAll == null) 174 { 175 _ifacesAll = getAggregate().GetTypeManager().SubstTypeArray(getAggregate().GetIfacesAll(), GetTypeArgsAll()); 176 } 177 return _ifacesAll; 178 } 179 GetWinRTCollectionIfacesAll(SymbolLoader pSymbolLoader)180 public TypeArray GetWinRTCollectionIfacesAll(SymbolLoader pSymbolLoader) 181 { 182 if (_winrtifacesAll == null) 183 { 184 TypeArray ifaces = GetIfacesAll(); 185 System.Collections.Generic.List<CType> typeList = new System.Collections.Generic.List<CType>(); 186 187 for (int i = 0; i < ifaces.Count; i++) 188 { 189 AggregateType type = ifaces[i] as AggregateType; 190 Debug.Assert(type.isInterfaceType()); 191 192 if (type.IsCollectionType()) 193 { 194 typeList.Add(type); 195 } 196 } 197 _winrtifacesAll = pSymbolLoader.getBSymmgr().AllocParams(typeList.Count, typeList.ToArray()); 198 } 199 return _winrtifacesAll; 200 } 201 } 202 } 203 204