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