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