001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.types;
018
019 import kotlin.Function1;
020 import kotlin.KotlinPackage;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
024 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
025 import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
026 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
027 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
028 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
029 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
030
031 import java.util.*;
032
033 import static org.jetbrains.jet.lang.types.TypeUtils.topologicallySortSuperclassesAndRecordAllInstances;
034 import static org.jetbrains.jet.lang.types.Variance.IN_VARIANCE;
035 import static org.jetbrains.jet.lang.types.Variance.OUT_VARIANCE;
036
037 public class CommonSupertypes {
038 @Nullable
039 public static JetType commonSupertypeForNonDenotableTypes(@NotNull Collection<JetType> types) {
040 if (types.isEmpty()) return null;
041 if (types.size() == 1) {
042 JetType type = types.iterator().next();
043 if (type.getConstructor() instanceof IntersectionTypeConstructor) {
044 return commonSupertypeForNonDenotableTypes(type.getConstructor().getSupertypes());
045 }
046 }
047 return commonSupertype(types);
048 }
049
050 @NotNull
051 public static JetType commonSupertype(@NotNull Collection<JetType> types) {
052 // Recursion should not be significantly deeper than the deepest type in question
053 // It can be slightly deeper, though: e.g. when initial types are simple, but their supertypes are complex
054 return findCommonSupertype(types, 0, maxDepth(types) + 3);
055 }
056
057 private static int maxDepth(@NotNull Collection<JetType> types) {
058 int max = 0;
059 for (JetType type : types) {
060 int depth = depth(type);
061 if (max < depth) {
062 max = depth;
063 }
064 }
065 return max;
066 }
067
068 private static int depth(@NotNull JetType type) {
069 return 1 + maxDepth(KotlinPackage.map(type.getArguments(), new Function1<TypeProjection, JetType>() {
070 @Override
071 public JetType invoke(TypeProjection projection) {
072 return projection.getType();
073 }
074 }));
075 }
076
077 @NotNull
078 public static JetType findCommonSupertype(@NotNull Collection<JetType> types, int recursionDepth, int maxDepth) {
079 assert recursionDepth <= maxDepth : "Recursion depth exceeded: " + recursionDepth + " > " + maxDepth + " for types " + types;
080 boolean hasFlexible = false;
081 List<JetType> upper = new ArrayList<JetType>(types.size());
082 List<JetType> lower = new ArrayList<JetType>(types.size());
083 for (JetType type : types) {
084 if (TypesPackage.isFlexible(type)) {
085 hasFlexible = true;
086 upper.add(TypesPackage.flexibility(type).getUpperBound());
087 lower.add(TypesPackage.flexibility(type).getLowerBound());
088 }
089 else {
090 upper.add(type);
091 lower.add(type);
092 }
093 }
094
095 if (!hasFlexible) return commonSuperTypeForInflexible(types, recursionDepth, maxDepth);
096 return DelegatingFlexibleType.OBJECT$.create(
097 commonSuperTypeForInflexible(lower, recursionDepth, maxDepth),
098 commonSuperTypeForInflexible(upper, recursionDepth, maxDepth)
099 );
100 }
101
102 @NotNull
103 private static JetType commonSuperTypeForInflexible(@NotNull Collection<JetType> types, int recursionDepth, int maxDepth) {
104 assert !types.isEmpty();
105 Collection<JetType> typeSet = new HashSet<JetType>(types);
106 if (typeSet.size() == 1) return typeSet.iterator().next();
107
108 // If any of the types is nullable, the result must be nullable
109 // This also removed Nothing and Nothing? because they are subtypes of everything else
110 boolean nullable = false;
111 for (Iterator<JetType> iterator = typeSet.iterator(); iterator.hasNext();) {
112 JetType type = iterator.next();
113 assert type != null;
114 assert !TypesPackage.isFlexible(type) : "Flexible type " + type + " passed to commonSuperTypeForInflexible";
115 if (KotlinBuiltIns.getInstance().isNothingOrNullableNothing(type)) {
116 iterator.remove();
117 }
118 if (type.isError()) {
119 return ErrorUtils.createErrorType("Supertype of error type " + type);
120 }
121 nullable |= type.isNullable();
122 }
123
124 // Everything deleted => it's Nothing or Nothing?
125 if (typeSet.isEmpty()) {
126 // TODO : attributes
127 return nullable ? KotlinBuiltIns.getInstance().getNullableNothingType() : KotlinBuiltIns.getInstance().getNothingType();
128 }
129
130 if (typeSet.size() == 1) {
131 return TypeUtils.makeNullableIfNeeded(typeSet.iterator().next(), nullable);
132 }
133
134 // constructor of the supertype -> all of its instantiations occurring as supertypes
135 Map<TypeConstructor, Set<JetType>> commonSupertypes = computeCommonRawSupertypes(typeSet);
136 while (commonSupertypes.size() > 1) {
137 Set<JetType> merge = new HashSet<JetType>();
138 for (Set<JetType> supertypes : commonSupertypes.values()) {
139 merge.addAll(supertypes);
140 }
141 commonSupertypes = computeCommonRawSupertypes(merge);
142 }
143 assert !commonSupertypes.isEmpty() : commonSupertypes + " <- " + types;
144
145 // constructor of the supertype -> all of its instantiations occurring as supertypes
146 Map.Entry<TypeConstructor, Set<JetType>> entry = commonSupertypes.entrySet().iterator().next();
147
148 // Reconstructing type arguments if possible
149 JetType result = computeSupertypeProjections(entry.getKey(), entry.getValue(), recursionDepth, maxDepth);
150 return TypeUtils.makeNullableIfNeeded(result, nullable);
151 }
152
153 // Raw supertypes are superclasses w/o type arguments
154 // @return TypeConstructor -> all instantiations of this constructor occurring as supertypes
155 @NotNull
156 private static Map<TypeConstructor, Set<JetType>> computeCommonRawSupertypes(@NotNull Collection<JetType> types) {
157 assert !types.isEmpty();
158
159 Map<TypeConstructor, Set<JetType>> constructorToAllInstances = new HashMap<TypeConstructor, Set<JetType>>();
160 Set<TypeConstructor> commonSuperclasses = null;
161
162 List<TypeConstructor> order = null;
163 for (JetType type : types) {
164 Set<TypeConstructor> visited = new HashSet<TypeConstructor>();
165 order = topologicallySortSuperclassesAndRecordAllInstances(type, constructorToAllInstances, visited);
166
167 if (commonSuperclasses == null) {
168 commonSuperclasses = visited;
169 }
170 else {
171 commonSuperclasses.retainAll(visited);
172 }
173 }
174 assert order != null;
175
176 Set<TypeConstructor> notSource = new HashSet<TypeConstructor>();
177 Map<TypeConstructor, Set<JetType>> result = new HashMap<TypeConstructor, Set<JetType>>();
178 for (TypeConstructor superConstructor : order) {
179 if (!commonSuperclasses.contains(superConstructor)) {
180 continue;
181 }
182
183 if (!notSource.contains(superConstructor)) {
184 result.put(superConstructor, constructorToAllInstances.get(superConstructor));
185 markAll(superConstructor, notSource);
186 }
187 }
188
189 return result;
190 }
191
192 // constructor - type constructor of a supertype to be instantiated
193 // types - instantiations of constructor occurring as supertypes of classes we are trying to intersect
194 @NotNull
195 private static JetType computeSupertypeProjections(@NotNull TypeConstructor constructor, @NotNull Set<JetType> types, int recursionDepth, int maxDepth) {
196 // we assume that all the given types are applications of the same type constructor
197
198 assert !types.isEmpty();
199
200 if (types.size() == 1) {
201 return types.iterator().next();
202 }
203
204 List<TypeParameterDescriptor> parameters = constructor.getParameters();
205 List<TypeProjection> newProjections = new ArrayList<TypeProjection>();
206 for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
207 TypeParameterDescriptor parameterDescriptor = parameters.get(i);
208 Set<TypeProjection> typeProjections = new HashSet<TypeProjection>();
209 for (JetType type : types) {
210 typeProjections.add(type.getArguments().get(i));
211 }
212 newProjections.add(computeSupertypeProjection(parameterDescriptor, typeProjections, recursionDepth, maxDepth));
213 }
214
215 boolean nullable = false;
216 for (JetType type : types) {
217 nullable |= type.isNullable();
218 }
219
220 // TODO : attributes?
221 JetScope newScope = JetScope.EMPTY;
222 DeclarationDescriptor declarationDescriptor = constructor.getDeclarationDescriptor();
223 if (declarationDescriptor instanceof ClassDescriptor) {
224 newScope = ((ClassDescriptor) declarationDescriptor).getMemberScope(newProjections);
225 }
226 return new JetTypeImpl(Annotations.EMPTY, constructor, nullable, newProjections, newScope);
227 }
228
229 @NotNull
230 private static TypeProjection computeSupertypeProjection(
231 @NotNull TypeParameterDescriptor parameterDescriptor,
232 @NotNull Set<TypeProjection> typeProjections,
233 int recursionDepth, int maxDepth
234 ) {
235 if (typeProjections.size() == 1) {
236 return typeProjections.iterator().next();
237 }
238
239 if (recursionDepth >= maxDepth) {
240 // If recursion is too deep, we cut it by taking <out Any?> as an ultimate supertype argument
241 // Example: class A : Base<A>; class B : Base<B>, commonSuperType(A, B) = Base<out Any?>
242 return new TypeProjectionImpl(OUT_VARIANCE, KotlinBuiltIns.getInstance().getNullableAnyType());
243 }
244
245 Set<JetType> ins = new HashSet<JetType>();
246 Set<JetType> outs = new HashSet<JetType>();
247
248 Variance variance = parameterDescriptor.getVariance();
249 switch (variance) {
250 case INVARIANT:
251 // Nothing
252 break;
253 case IN_VARIANCE:
254 outs = null;
255 break;
256 case OUT_VARIANCE:
257 ins = null;
258 break;
259 }
260
261 for (TypeProjection projection : typeProjections) {
262 Variance projectionKind = projection.getProjectionKind();
263 if (projectionKind.allowsInPosition()) {
264 if (ins != null) {
265 ins.add(projection.getType());
266 }
267 }
268 else {
269 ins = null;
270 }
271
272 if (projectionKind.allowsOutPosition()) {
273 if (outs != null) {
274 outs.add(projection.getType());
275 }
276 }
277 else {
278 outs = null;
279 }
280 }
281
282 if (outs != null) {
283 Variance projectionKind = variance == OUT_VARIANCE ? Variance.INVARIANT : OUT_VARIANCE;
284 return new TypeProjectionImpl(projectionKind, findCommonSupertype(outs, recursionDepth + 1, maxDepth));
285 }
286 if (ins != null) {
287 JetType intersection = TypeUtils.intersect(JetTypeChecker.DEFAULT, ins);
288 if (intersection == null) {
289 return new TypeProjectionImpl(OUT_VARIANCE, findCommonSupertype(parameterDescriptor.getUpperBounds(), recursionDepth + 1, maxDepth));
290 }
291 Variance projectionKind = variance == IN_VARIANCE ? Variance.INVARIANT : IN_VARIANCE;
292 return new TypeProjectionImpl(projectionKind, intersection);
293 }
294 else {
295 Variance projectionKind = variance == OUT_VARIANCE ? Variance.INVARIANT : OUT_VARIANCE;
296 return new TypeProjectionImpl(projectionKind, findCommonSupertype(parameterDescriptor.getUpperBounds(), recursionDepth + 1, maxDepth));
297 }
298 }
299
300 private static void markAll(@NotNull TypeConstructor typeConstructor, @NotNull Set<TypeConstructor> markerSet) {
301 markerSet.add(typeConstructor);
302 for (JetType type : typeConstructor.getSupertypes()) {
303 markAll(type.getConstructor(), markerSet);
304 }
305 }
306 }