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