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