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            Flexibility flexibility = type.getCapability(Flexibility.class);
537            if (flexibility != null
538                    && (containsSpecialType(flexibility.getLowerBound(), isSpecialType) || containsSpecialType(flexibility.getUpperBound(), isSpecialType))) {
539                return true;
540            }
541            for (TypeProjection projection : type.getArguments()) {
542                if (containsSpecialType(projection.getType(), isSpecialType)) return true;
543            }
544            return false;
545        }
546    
547        @NotNull
548        public static TypeProjection makeStarProjection(@NotNull TypeParameterDescriptor parameterDescriptor) {
549            return new TypeProjectionImpl(parameterDescriptor.getVariance() == Variance.OUT_VARIANCE
550                                          ? Variance.INVARIANT
551                                          : Variance.OUT_VARIANCE, parameterDescriptor.getUpperBoundsAsType());
552        }
553    
554        @Nullable
555        public static JetType commonSupertypeForNumberTypes(@NotNull Collection<JetType> numberLowerBounds) {
556            if (numberLowerBounds.isEmpty()) return null;
557            Set<JetType> intersectionOfSupertypes = getIntersectionOfSupertypes(numberLowerBounds);
558            JetType primitiveNumberType = getDefaultPrimitiveNumberType(intersectionOfSupertypes);
559            if (primitiveNumberType != null) {
560                return primitiveNumberType;
561            }
562            return CommonSupertypes.commonSupertype(numberLowerBounds);
563        }
564    
565        @NotNull
566        private static Set<JetType> getIntersectionOfSupertypes(@NotNull Collection<JetType> types) {
567            Set<JetType> upperBounds = new HashSet<JetType>();
568            for (JetType type : types) {
569                Collection<JetType> supertypes = type.getConstructor().getSupertypes();
570                if (upperBounds.isEmpty()) {
571                    upperBounds.addAll(supertypes);
572                }
573                else {
574                    upperBounds.retainAll(supertypes);
575                }
576            }
577            return upperBounds;
578        }
579    
580        @NotNull
581        public static JetType getDefaultPrimitiveNumberType(@NotNull IntegerValueTypeConstructor numberValueTypeConstructor) {
582            JetType type = getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
583            assert type != null : "Strange number value type constructor: " + numberValueTypeConstructor + ". " +
584                                  "Super types doesn't contain double, int or long: " + numberValueTypeConstructor.getSupertypes();
585            return type;
586        }
587    
588        @Nullable
589        private static JetType getDefaultPrimitiveNumberType(@NotNull Collection<JetType> supertypes) {
590            JetType doubleType = KotlinBuiltIns.getInstance().getDoubleType();
591            if (supertypes.contains(doubleType)) {
592                return doubleType;
593            }
594            JetType intType = KotlinBuiltIns.getInstance().getIntType();
595            if (supertypes.contains(intType)) {
596                return intType;
597            }
598            JetType longType = KotlinBuiltIns.getInstance().getLongType();
599            if (supertypes.contains(longType)) {
600                return longType;
601            }
602            return null;
603        }
604    
605        @NotNull
606        public static JetType getPrimitiveNumberType(
607                @NotNull IntegerValueTypeConstructor numberValueTypeConstructor,
608                @NotNull JetType expectedType
609        ) {
610            if (noExpectedType(expectedType) || expectedType.isError()) {
611                return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
612            }
613            for (JetType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) {
614                if (JetTypeChecker.DEFAULT.isSubtypeOf(primitiveNumberType, expectedType)) {
615                    return primitiveNumberType;
616                }
617            }
618            return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
619        }
620    
621        public static List<TypeConstructor> topologicallySortSuperclassesAndRecordAllInstances(
622                @NotNull JetType type,
623                @NotNull final Map<TypeConstructor, Set<JetType>> constructorToAllInstances,
624                @NotNull final Set<TypeConstructor> visited
625        ) {
626            return DFS.dfs(
627                    Collections.singletonList(type),
628                    new DFS.Neighbors<JetType>() {
629                        @NotNull
630                        @Override
631                        public Iterable<JetType> getNeighbors(JetType current) {
632                            TypeSubstitutor substitutor = TypeSubstitutor.create(current);
633                            Collection<JetType> supertypes = current.getConstructor().getSupertypes();
634                            List<JetType> result = new ArrayList<JetType>(supertypes.size());
635                            for (JetType supertype : supertypes) {
636                                if (visited.contains(supertype.getConstructor())) {
637                                    continue;
638                                }
639                                result.add(substitutor.safeSubstitute(supertype, Variance.INVARIANT));
640                            }
641                            return result;
642                        }
643                    },
644                    new DFS.Visited<JetType>() {
645                        @Override
646                        public boolean checkAndMarkVisited(JetType current) {
647                            return visited.add(current.getConstructor());
648                        }
649                    },
650                    new DFS.NodeHandlerWithListResult<JetType, TypeConstructor>() {
651                        @Override
652                        public boolean beforeChildren(JetType current) {
653                            TypeConstructor constructor = current.getConstructor();
654    
655                            Set<JetType> instances = constructorToAllInstances.get(constructor);
656                            if (instances == null) {
657                                instances = new HashSet<JetType>();
658                                constructorToAllInstances.put(constructor, instances);
659                            }
660                            instances.add(current);
661    
662                            return true;
663                        }
664    
665                        @Override
666                        public void afterChildren(JetType current) {
667                            result.addFirst(current.getConstructor());
668                        }
669                    }
670            );
671        }
672    
673        public static TypeSubstitutor makeConstantSubstitutor(Collection<TypeParameterDescriptor> typeParameterDescriptors, JetType type) {
674            final Set<TypeConstructor> constructors = UtilsPackage.newHashSetWithExpectedSize(typeParameterDescriptors.size());
675            for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) {
676                constructors.add(typeParameterDescriptor.getTypeConstructor());
677            }
678            final TypeProjection projection = new TypeProjectionImpl(type);
679    
680            return TypeSubstitutor.create(new TypeSubstitution() {
681                @Override
682                public TypeProjection get(TypeConstructor key) {
683                    if (constructors.contains(key)) {
684                        return projection;
685                    }
686                    return null;
687                }
688    
689                @Override
690                public boolean isEmpty() {
691                    return false;
692                }
693            });
694        }
695    
696        public static TypeSubstitutor makeSubstitutorForTypeParametersMap(
697               @NotNull final Map<TypeParameterDescriptor, TypeProjection> substitutionContext
698        ) {
699            return TypeSubstitutor.create(new TypeSubstitution() {
700                @Nullable
701                @Override
702                public TypeProjection get(TypeConstructor key) {
703                    DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
704                    if (declarationDescriptor instanceof TypeParameterDescriptor) {
705                        TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
706                        return substitutionContext.get(descriptor);
707                    }
708                    return null;
709                }
710    
711                @Override
712                public boolean isEmpty() {
713                    return substitutionContext.isEmpty();
714                }
715    
716                @Override
717                public String toString() {
718                    return substitutionContext.toString();
719                }
720            });
721        }
722    
723        private static abstract class AbstractTypeWithKnownNullability extends AbstractJetType {
724            private final JetType delegate;
725    
726            private AbstractTypeWithKnownNullability(@NotNull JetType delegate) {
727                this.delegate = delegate;
728            }
729    
730            @Override
731            @NotNull
732            public TypeConstructor getConstructor() {
733                return delegate.getConstructor();
734            }
735    
736            @Override
737            @NotNull
738            public List<TypeProjection> getArguments() {
739                return delegate.getArguments();
740            }
741    
742            @Override
743            public abstract boolean isNullable();
744    
745            @Override
746            @NotNull
747            public JetScope getMemberScope() {
748                return delegate.getMemberScope();
749            }
750    
751            @Override
752            public boolean isError() {
753                return delegate.isError();
754            }
755    
756            @Override
757            @NotNull
758            public Annotations getAnnotations() {
759                return delegate.getAnnotations();
760            }
761        }
762    
763        private static class NullableType extends AbstractTypeWithKnownNullability {
764    
765            private NullableType(@NotNull JetType delegate) {
766                super(delegate);
767            }
768    
769            @Override
770            public boolean isNullable() {
771                return true;
772            }
773        }
774    
775        private static class NotNullType extends AbstractTypeWithKnownNullability {
776    
777            private NotNullType(@NotNull JetType delegate) {
778                super(delegate);
779            }
780    
781            @Override
782            public boolean isNullable() {
783                return false;
784            }
785        }
786    
787    }