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 }