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 kotlin.Unit;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
025 import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
026 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
027 import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
028 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
029 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
030 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
031 import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstructor;
032 import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
033 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
034 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
035 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
036 import org.jetbrains.jet.utils.DFS;
037 import org.jetbrains.jet.utils.UtilsPackage;
038
039 import java.util.*;
040
041 public class TypeUtils {
042 public static final JetType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
043 public static final JetType PLACEHOLDER_FUNCTION_TYPE = ErrorUtils.createErrorTypeWithCustomDebugName("PLACEHOLDER_FUNCTION_TYPE");
044
045 public static final JetType CANT_INFER_LAMBDA_PARAM_TYPE = ErrorUtils.createErrorType("Cannot be inferred");
046
047 public static class SpecialType implements JetType {
048 private final String name;
049
050 public SpecialType(String name) {
051 this.name = name;
052 }
053
054 @NotNull
055 @Override
056 public TypeConstructor getConstructor() {
057 throw new IllegalStateException(name);
058 }
059
060 @NotNull
061 @Override
062 public List<TypeProjection> getArguments() {
063 throw new IllegalStateException(name);
064 }
065
066 @Override
067 public boolean isNullable() {
068 throw new IllegalStateException(name);
069 }
070
071 @NotNull
072 @Override
073 public JetScope getMemberScope() {
074 throw new IllegalStateException(name);
075 }
076
077 @Override
078 public boolean isError() {
079 return false;
080 }
081
082 @NotNull
083 @Override
084 public Annotations getAnnotations() {
085 throw new IllegalStateException(name);
086 }
087
088 @Nullable
089 @Override
090 public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
091 return null;
092 }
093
094 @Override
095 public String toString() {
096 return name;
097 }
098 }
099
100 public static final JetType NO_EXPECTED_TYPE = new SpecialType("NO_EXPECTED_TYPE");
101
102 public static final JetType UNIT_EXPECTED_TYPE = new SpecialType("UNIT_EXPECTED_TYPE");
103
104 public static boolean noExpectedType(@NotNull JetType type) {
105 return type == NO_EXPECTED_TYPE || type == UNIT_EXPECTED_TYPE;
106 }
107
108 @NotNull
109 public static JetType makeNullable(@NotNull JetType type) {
110 return makeNullableAsSpecified(type, true);
111 }
112
113 @NotNull
114 public static JetType makeNotNullable(@NotNull JetType type) {
115 return makeNullableAsSpecified(type, false);
116 }
117
118 @NotNull
119 public static JetType makeNullableAsSpecified(@NotNull JetType type, boolean nullable) {
120 NullAwareness nullAwareness = type.getCapability(NullAwareness.class);
121 if (nullAwareness != null) {
122 return nullAwareness.makeNullableAsSpecified(nullable);
123 }
124
125 // Wrapping serves two purposes here
126 // 1. It's requires less memory than copying with a changed nullability flag: a copy has many fields, while a wrapper has only one
127 // 2. It preserves laziness of types
128
129 // Unwrap to avoid long delegation call chains
130 if (type instanceof AbstractTypeWithKnownNullability) {
131 return makeNullableAsSpecified(((AbstractTypeWithKnownNullability) type).delegate, nullable);
132 }
133
134 // checking to preserve laziness
135 if (!(type instanceof LazyType) && type.isNullable() == nullable) {
136 return type;
137 }
138
139 return nullable ? new NullableType(type) : new NotNullType(type);
140 }
141
142 @NotNull
143 public static JetType makeNullableIfNeeded(@NotNull JetType type, boolean nullable) {
144 if (nullable) {
145 return makeNullable(type);
146 }
147 return type;
148 }
149
150 public static boolean isIntersectionEmpty(@NotNull JetType typeA, @NotNull JetType typeB) {
151 return intersect(JetTypeChecker.DEFAULT, new LinkedHashSet<JetType>(Arrays.asList(typeA, typeB))) == null;
152 }
153
154 @Nullable
155 public static JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set<JetType> types) {
156 if (types.isEmpty()) {
157 return KotlinBuiltIns.getInstance().getNullableAnyType();
158 }
159
160 if (types.size() == 1) {
161 return types.iterator().next();
162 }
163
164 // Intersection of T1..Tn is an intersection of their non-null versions,
165 // made nullable is they all were nullable
166 boolean allNullable = true;
167 boolean nothingTypePresent = false;
168 List<JetType> nullabilityStripped = new ArrayList<JetType>(types.size());
169 for (JetType type : types) {
170 nothingTypePresent |= KotlinBuiltIns.getInstance().isNothingOrNullableNothing(type);
171 allNullable &= type.isNullable();
172 nullabilityStripped.add(makeNotNullable(type));
173 }
174
175 if (nothingTypePresent) {
176 return allNullable ? KotlinBuiltIns.getInstance().getNullableNothingType() : KotlinBuiltIns.getInstance().getNothingType();
177 }
178
179 // Now we remove types that have subtypes in the list
180 List<JetType> resultingTypes = new ArrayList<JetType>();
181 outer:
182 for (JetType type : nullabilityStripped) {
183 if (!canHaveSubtypes(typeChecker, type)) {
184 for (JetType other : nullabilityStripped) {
185 // It makes sense to check for subtyping (other <: type), despite that
186 // type is not supposed to be open, for there're enums
187 if (!TypeUnifier.mayBeEqual(type, other) && !typeChecker.isSubtypeOf(type, other) && !typeChecker.isSubtypeOf(other, type)) {
188 return null;
189 }
190 }
191 return makeNullableAsSpecified(type, allNullable);
192 }
193 else {
194 for (JetType other : nullabilityStripped) {
195 if (!type.equals(other) && typeChecker.isSubtypeOf(other, type)) {
196 continue outer;
197 }
198
199 }
200 }
201
202 // Don't add type if it is already present, to avoid trivial type intersections in result
203 for (JetType other : resultingTypes) {
204 if (typeChecker.equalTypes(other, type)) {
205 continue outer;
206 }
207 }
208 resultingTypes.add(type);
209 }
210
211 if (resultingTypes.size() == 1) {
212 return makeNullableAsSpecified(resultingTypes.get(0), allNullable);
213 }
214
215
216 TypeConstructor constructor = new IntersectionTypeConstructor(Annotations.EMPTY, resultingTypes);
217
218 JetScope[] scopes = new JetScope[resultingTypes.size()];
219 int i = 0;
220 for (JetType type : resultingTypes) {
221 scopes[i] = type.getMemberScope();
222 i++;
223 }
224
225 return new JetTypeImpl(
226 Annotations.EMPTY,
227 constructor,
228 allNullable,
229 Collections.<TypeProjection>emptyList(),
230 new ChainedScope(null, "member scope for intersection type " + constructor, scopes)); // TODO : check intersectibility, don't use a chanied scope
231 }
232
233 private static class TypeUnifier {
234 private static class TypeParameterUsage {
235 private final TypeParameterDescriptor typeParameterDescriptor;
236 private final Variance howTheTypeParameterIsUsed;
237
238 public TypeParameterUsage(TypeParameterDescriptor typeParameterDescriptor, Variance howTheTypeParameterIsUsed) {
239 this.typeParameterDescriptor = typeParameterDescriptor;
240 this.howTheTypeParameterIsUsed = howTheTypeParameterIsUsed;
241 }
242 }
243
244 public static boolean mayBeEqual(@NotNull JetType type, @NotNull JetType other) {
245 return unify(type, other);
246 }
247
248 private static boolean unify(JetType withParameters, JetType expected) {
249 // T -> how T is used
250 final Map<TypeParameterDescriptor, Variance> parameters = new HashMap<TypeParameterDescriptor, Variance>();
251 Function1<TypeParameterUsage, Unit> processor = new Function1<TypeParameterUsage, Unit>() {
252 @Override
253 public Unit invoke(TypeParameterUsage parameterUsage) {
254 Variance howTheTypeIsUsedBefore = parameters.get(parameterUsage.typeParameterDescriptor);
255 if (howTheTypeIsUsedBefore == null) {
256 howTheTypeIsUsedBefore = Variance.INVARIANT;
257 }
258 parameters.put(parameterUsage.typeParameterDescriptor,
259 parameterUsage.howTheTypeParameterIsUsed.superpose(howTheTypeIsUsedBefore));
260 return Unit.INSTANCE$;
261 }
262 };
263 processAllTypeParameters(withParameters, Variance.INVARIANT, processor);
264 processAllTypeParameters(expected, Variance.INVARIANT, processor);
265 ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
266 constraintSystem.registerTypeVariables(parameters);
267 constraintSystem.addSubtypeConstraint(withParameters, expected, ConstraintPosition.SPECIAL);
268
269 return constraintSystem.getStatus().isSuccessful();
270 }
271
272 private static void processAllTypeParameters(JetType type, Variance howThisTypeIsUsed, Function1<TypeParameterUsage, Unit> result) {
273 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
274 if (descriptor instanceof TypeParameterDescriptor) {
275 result.invoke(new TypeParameterUsage((TypeParameterDescriptor) descriptor, howThisTypeIsUsed));
276 }
277 for (TypeProjection projection : type.getArguments()) {
278 processAllTypeParameters(projection.getType(), projection.getProjectionKind(), result);
279 }
280 }
281 }
282
283 public static boolean canHaveSubtypes(JetTypeChecker typeChecker, JetType type) {
284 if (type.isNullable()) {
285 return true;
286 }
287 if (!type.getConstructor().isFinal()) {
288 return true;
289 }
290
291 List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
292 List<TypeProjection> arguments = type.getArguments();
293 for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
294 TypeParameterDescriptor parameterDescriptor = parameters.get(i);
295 TypeProjection typeProjection = arguments.get(i);
296 Variance projectionKind = typeProjection.getProjectionKind();
297 JetType argument = typeProjection.getType();
298
299 switch (parameterDescriptor.getVariance()) {
300 case INVARIANT:
301 switch (projectionKind) {
302 case INVARIANT:
303 if (lowerThanBound(typeChecker, argument, parameterDescriptor) || canHaveSubtypes(typeChecker, argument)) {
304 return true;
305 }
306 break;
307 case IN_VARIANCE:
308 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
309 return true;
310 }
311 break;
312 case OUT_VARIANCE:
313 if (canHaveSubtypes(typeChecker, argument)) {
314 return true;
315 }
316 break;
317 }
318 break;
319 case IN_VARIANCE:
320 if (projectionKind != Variance.OUT_VARIANCE) {
321 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
322 return true;
323 }
324 }
325 else {
326 if (canHaveSubtypes(typeChecker, argument)) {
327 return true;
328 }
329 }
330 break;
331 case OUT_VARIANCE:
332 if (projectionKind != Variance.IN_VARIANCE) {
333 if (canHaveSubtypes(typeChecker, argument)) {
334 return true;
335 }
336 }
337 else {
338 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
339 return true;
340 }
341 }
342 break;
343 }
344 }
345 return false;
346 }
347
348 private static boolean lowerThanBound(JetTypeChecker typeChecker, JetType argument, TypeParameterDescriptor parameterDescriptor) {
349 for (JetType bound : parameterDescriptor.getUpperBounds()) {
350 if (typeChecker.isSubtypeOf(argument, bound)) {
351 if (!argument.getConstructor().equals(bound.getConstructor())) {
352 return true;
353 }
354 }
355 }
356 return false;
357 }
358
359 @NotNull
360 public static JetType makeUnsubstitutedType(ClassDescriptor classDescriptor, JetScope unsubstitutedMemberScope) {
361 if (ErrorUtils.isError(classDescriptor)) {
362 return ErrorUtils.createErrorType("Unsubstituted type for " + classDescriptor);
363 }
364 TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
365 List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
366 return new JetTypeImpl(
367 Annotations.EMPTY,
368 typeConstructor,
369 false,
370 arguments,
371 unsubstitutedMemberScope
372 );
373 }
374
375 @NotNull
376 public static List<TypeProjection> getDefaultTypeProjections(List<TypeParameterDescriptor> parameters) {
377 List<TypeProjection> result = new ArrayList<TypeProjection>();
378 for (TypeParameterDescriptor parameterDescriptor : parameters) {
379 result.add(new TypeProjectionImpl(parameterDescriptor.getDefaultType()));
380 }
381 return result;
382 }
383
384 @NotNull
385 public static List<JetType> getImmediateSupertypes(@NotNull JetType type) {
386 boolean isNullable = type.isNullable();
387 TypeSubstitutor substitutor = TypeSubstitutor.create(type);
388 Collection<JetType> originalSupertypes = type.getConstructor().getSupertypes();
389 List<JetType> result = new ArrayList<JetType>(originalSupertypes.size());
390 for (JetType supertype : originalSupertypes) {
391 JetType substitutedType = substitutor.substitute(supertype, Variance.INVARIANT);
392 if (substitutedType != null) {
393 result.add(makeNullableIfNeeded(substitutedType, isNullable));
394 }
395 }
396 return result;
397 }
398
399 private static void collectAllSupertypes(@NotNull JetType type, @NotNull Set<JetType> result) {
400 List<JetType> immediateSupertypes = getImmediateSupertypes(type);
401 result.addAll(immediateSupertypes);
402 for (JetType supertype : immediateSupertypes) {
403 collectAllSupertypes(supertype, result);
404 }
405 }
406
407
408 @NotNull
409 public static Set<JetType> getAllSupertypes(@NotNull JetType type) {
410 // 15 is obtained by experimentation: JDK classes like ArrayList tend to have so many supertypes,
411 // the average number is lower
412 Set<JetType> result = new LinkedHashSet<JetType>(15);
413 collectAllSupertypes(type, result);
414 return result;
415 }
416
417 public static boolean hasNullableLowerBound(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
418 for (JetType bound : typeParameterDescriptor.getLowerBounds()) {
419 if (bound.isNullable()) {
420 return true;
421 }
422 }
423 return false;
424 }
425
426 /**
427 * A work-around of the generic nullability problem in the type checker
428 * @return true if a value of this type can be null
429 */
430 public static boolean isNullableType(@NotNull JetType type) {
431 if (type.isNullable()) {
432 return true;
433 }
434 if (TypesPackage.isFlexible(type) && isNullableType(TypesPackage.flexibility(type).getUpperBound())) {
435 return true;
436 }
437 if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
438 return hasNullableSuperType(type);
439 }
440 return false;
441 }
442
443 public static boolean hasNullableSuperType(@NotNull JetType type) {
444 if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
445 // A class/trait cannot have a nullable supertype
446 return false;
447 }
448
449 for (JetType supertype : getImmediateSupertypes(type)) {
450 if (supertype.isNullable()) return true;
451 if (hasNullableSuperType(supertype)) return true;
452 }
453
454 return false;
455 }
456
457 @Nullable
458 public static ClassDescriptor getClassDescriptor(@NotNull JetType type) {
459 DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
460 if (declarationDescriptor instanceof ClassDescriptor) {
461 return (ClassDescriptor) declarationDescriptor;
462 }
463 return null;
464 }
465
466 @NotNull
467 public static JetType substituteParameters(@NotNull ClassDescriptor clazz, @NotNull List<JetType> typeArguments) {
468 List<TypeProjection> projections = KotlinPackage.map(typeArguments, new Function1<JetType, TypeProjection>() {
469 @Override
470 public TypeProjection invoke(JetType type) {
471 return new TypeProjectionImpl(type);
472 }
473 });
474
475 return substituteProjectionsForParameters(clazz, projections);
476 }
477
478 @NotNull
479 public static JetType substituteProjectionsForParameters(@NotNull ClassDescriptor clazz, @NotNull List<TypeProjection> projections) {
480 List<TypeParameterDescriptor> clazzTypeParameters = clazz.getTypeConstructor().getParameters();
481 if (clazzTypeParameters.size() != projections.size()) {
482 throw new IllegalArgumentException("type parameter counts do not match: " + clazz + ", " + projections);
483 }
484
485 Map<TypeConstructor, TypeProjection> substitutions = UtilsPackage.newHashMapWithExpectedSize(clazzTypeParameters.size());
486
487 for (int i = 0; i < clazzTypeParameters.size(); ++i) {
488 TypeConstructor typeConstructor = clazzTypeParameters.get(i).getTypeConstructor();
489 substitutions.put(typeConstructor, projections.get(i));
490 }
491
492 return TypeSubstitutor.create(substitutions).substitute(clazz.getDefaultType(), Variance.INVARIANT);
493 }
494
495 public static boolean equalTypes(@NotNull JetType a, @NotNull JetType b) {
496 return JetTypeChecker.DEFAULT.isSubtypeOf(a, b) && JetTypeChecker.DEFAULT.isSubtypeOf(b, a);
497 }
498
499 public static boolean dependsOnTypeParameters(@NotNull JetType type, @NotNull Collection<TypeParameterDescriptor> typeParameters) {
500 return dependsOnTypeConstructors(type, KotlinPackage.map(
501 typeParameters,
502 new Function1<TypeParameterDescriptor, TypeConstructor>() {
503 @Override
504 public TypeConstructor invoke(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
505 return typeParameterDescriptor.getTypeConstructor();
506 }
507 }
508 ));
509 }
510
511 public static boolean dependsOnTypeConstructors(@NotNull JetType type, @NotNull Collection<TypeConstructor> typeParameterConstructors) {
512 if (typeParameterConstructors.contains(type.getConstructor())) return true;
513 for (TypeProjection typeProjection : type.getArguments()) {
514 if (dependsOnTypeConstructors(typeProjection.getType(), typeParameterConstructors)) {
515 return true;
516 }
517 }
518 return false;
519 }
520
521 public static boolean containsSpecialType(@Nullable JetType type, @NotNull final JetType specialType) {
522 return containsSpecialType(type, new Function1<JetType, Boolean>() {
523 @Override
524 public Boolean invoke(JetType type) {
525 return specialType.equals(type);
526 }
527 });
528 }
529
530 public static boolean containsSpecialType(
531 @Nullable JetType type,
532 @NotNull Function1<JetType, Boolean> isSpecialType
533 ) {
534 if (type == null) return false;
535 if (isSpecialType.invoke(type)) return true;
536 for (TypeProjection projection : type.getArguments()) {
537 if (containsSpecialType(projection.getType(), isSpecialType)) return true;
538 }
539 return false;
540 }
541
542 @NotNull
543 public static TypeProjection makeStarProjection(@NotNull TypeParameterDescriptor parameterDescriptor) {
544 return new TypeProjectionImpl(parameterDescriptor.getVariance() == Variance.OUT_VARIANCE
545 ? Variance.INVARIANT
546 : Variance.OUT_VARIANCE, parameterDescriptor.getUpperBoundsAsType());
547 }
548
549 @Nullable
550 public static JetType commonSupertypeForNumberTypes(@NotNull Collection<JetType> numberLowerBounds) {
551 if (numberLowerBounds.isEmpty()) return null;
552 Set<JetType> intersectionOfSupertypes = getIntersectionOfSupertypes(numberLowerBounds);
553 JetType primitiveNumberType = getDefaultPrimitiveNumberType(intersectionOfSupertypes);
554 if (primitiveNumberType != null) {
555 return primitiveNumberType;
556 }
557 return CommonSupertypes.commonSupertype(numberLowerBounds);
558 }
559
560 @NotNull
561 private static Set<JetType> getIntersectionOfSupertypes(@NotNull Collection<JetType> types) {
562 Set<JetType> upperBounds = new HashSet<JetType>();
563 for (JetType type : types) {
564 Collection<JetType> supertypes = type.getConstructor().getSupertypes();
565 if (upperBounds.isEmpty()) {
566 upperBounds.addAll(supertypes);
567 }
568 else {
569 upperBounds.retainAll(supertypes);
570 }
571 }
572 return upperBounds;
573 }
574
575 @NotNull
576 public static JetType getDefaultPrimitiveNumberType(@NotNull IntegerValueTypeConstructor numberValueTypeConstructor) {
577 JetType type = getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
578 assert type != null : "Strange number value type constructor: " + numberValueTypeConstructor + ". " +
579 "Super types doesn't contain double, int or long: " + numberValueTypeConstructor.getSupertypes();
580 return type;
581 }
582
583 @Nullable
584 private static JetType getDefaultPrimitiveNumberType(@NotNull Collection<JetType> supertypes) {
585 JetType doubleType = KotlinBuiltIns.getInstance().getDoubleType();
586 if (supertypes.contains(doubleType)) {
587 return doubleType;
588 }
589 JetType intType = KotlinBuiltIns.getInstance().getIntType();
590 if (supertypes.contains(intType)) {
591 return intType;
592 }
593 JetType longType = KotlinBuiltIns.getInstance().getLongType();
594 if (supertypes.contains(longType)) {
595 return longType;
596 }
597 return null;
598 }
599
600 @NotNull
601 public static JetType getPrimitiveNumberType(
602 @NotNull IntegerValueTypeConstructor numberValueTypeConstructor,
603 @NotNull JetType expectedType
604 ) {
605 if (noExpectedType(expectedType) || expectedType.isError()) {
606 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
607 }
608 for (JetType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) {
609 if (JetTypeChecker.DEFAULT.isSubtypeOf(primitiveNumberType, expectedType)) {
610 return primitiveNumberType;
611 }
612 }
613 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
614 }
615
616 public static List<TypeConstructor> topologicallySortSuperclassesAndRecordAllInstances(
617 @NotNull JetType type,
618 @NotNull final Map<TypeConstructor, Set<JetType>> constructorToAllInstances,
619 @NotNull final Set<TypeConstructor> visited
620 ) {
621 return DFS.dfs(
622 Collections.singletonList(type),
623 new DFS.Neighbors<JetType>() {
624 @NotNull
625 @Override
626 public Iterable<JetType> getNeighbors(JetType current) {
627 TypeSubstitutor substitutor = TypeSubstitutor.create(current);
628 Collection<JetType> supertypes = current.getConstructor().getSupertypes();
629 List<JetType> result = new ArrayList<JetType>(supertypes.size());
630 for (JetType supertype : supertypes) {
631 if (visited.contains(supertype.getConstructor())) {
632 continue;
633 }
634 result.add(substitutor.safeSubstitute(supertype, Variance.INVARIANT));
635 }
636 return result;
637 }
638 },
639 new DFS.Visited<JetType>() {
640 @Override
641 public boolean checkAndMarkVisited(JetType current) {
642 return visited.add(current.getConstructor());
643 }
644 },
645 new DFS.NodeHandlerWithListResult<JetType, TypeConstructor>() {
646 @Override
647 public boolean beforeChildren(JetType current) {
648 TypeConstructor constructor = current.getConstructor();
649
650 Set<JetType> instances = constructorToAllInstances.get(constructor);
651 if (instances == null) {
652 instances = new HashSet<JetType>();
653 constructorToAllInstances.put(constructor, instances);
654 }
655 instances.add(current);
656
657 return true;
658 }
659
660 @Override
661 public void afterChildren(JetType current) {
662 result.addFirst(current.getConstructor());
663 }
664 }
665 );
666 }
667
668 public static TypeSubstitutor makeConstantSubstitutor(Collection<TypeParameterDescriptor> typeParameterDescriptors, JetType type) {
669 final Set<TypeConstructor> constructors = UtilsPackage.newHashSetWithExpectedSize(typeParameterDescriptors.size());
670 for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) {
671 constructors.add(typeParameterDescriptor.getTypeConstructor());
672 }
673 final TypeProjection projection = new TypeProjectionImpl(type);
674
675 return TypeSubstitutor.create(new TypeSubstitution() {
676 @Override
677 public TypeProjection get(TypeConstructor key) {
678 if (constructors.contains(key)) {
679 return projection;
680 }
681 return null;
682 }
683
684 @Override
685 public boolean isEmpty() {
686 return false;
687 }
688 });
689 }
690
691 public static TypeSubstitutor makeSubstitutorForTypeParametersMap(
692 @NotNull final Map<TypeParameterDescriptor, TypeProjection> substitutionContext
693 ) {
694 return TypeSubstitutor.create(new TypeSubstitution() {
695 @Nullable
696 @Override
697 public TypeProjection get(TypeConstructor key) {
698 DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
699 if (declarationDescriptor instanceof TypeParameterDescriptor) {
700 TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
701 return substitutionContext.get(descriptor);
702 }
703 return null;
704 }
705
706 @Override
707 public boolean isEmpty() {
708 return substitutionContext.isEmpty();
709 }
710
711 @Override
712 public String toString() {
713 return substitutionContext.toString();
714 }
715 });
716 }
717
718 private static abstract class AbstractTypeWithKnownNullability extends AbstractJetType {
719 private final JetType delegate;
720
721 private AbstractTypeWithKnownNullability(@NotNull JetType delegate) {
722 this.delegate = delegate;
723 }
724
725 @Override
726 @NotNull
727 public TypeConstructor getConstructor() {
728 return delegate.getConstructor();
729 }
730
731 @Override
732 @NotNull
733 public List<TypeProjection> getArguments() {
734 return delegate.getArguments();
735 }
736
737 @Override
738 public abstract boolean isNullable();
739
740 @Override
741 @NotNull
742 public JetScope getMemberScope() {
743 return delegate.getMemberScope();
744 }
745
746 @Override
747 public boolean isError() {
748 return delegate.isError();
749 }
750
751 @Override
752 @NotNull
753 public Annotations getAnnotations() {
754 return delegate.getAnnotations();
755 }
756 }
757
758 private static class NullableType extends AbstractTypeWithKnownNullability {
759
760 private NullableType(@NotNull JetType delegate) {
761 super(delegate);
762 }
763
764 @Override
765 public boolean isNullable() {
766 return true;
767 }
768 }
769
770 private static class NotNullType extends AbstractTypeWithKnownNullability {
771
772 private NotNullType(@NotNull JetType delegate) {
773 super(delegate);
774 }
775
776 @Override
777 public boolean isNullable() {
778 return false;
779 }
780 }
781
782 }