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.*;
030 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
031 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListener;
032 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
033 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemWithPriorities;
034 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType;
035 import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstructor;
036 import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
037 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
038 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
039 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
040
041 import java.util.*;
042
043 public class TypeUtils {
044 public static class SpecialType implements JetType {
045 private final String name;
046
047 public SpecialType(String name) {
048 this.name = name;
049 }
050
051 @NotNull
052 @Override
053 public TypeConstructor getConstructor() {
054 throw new IllegalStateException(name);
055 }
056
057 @NotNull
058 @Override
059 public List<TypeProjection> getArguments() {
060 throw new IllegalStateException(name);
061 }
062
063 @Override
064 public boolean isNullable() {
065 throw new IllegalStateException(name);
066 }
067
068 @NotNull
069 @Override
070 public JetScope getMemberScope() {
071 throw new IllegalStateException(name);
072 }
073
074 @Override
075 public List<AnnotationDescriptor> getAnnotations() {
076 throw new IllegalStateException(name);
077 }
078
079 @Override
080 public String toString() {
081 return name;
082 }
083 }
084
085 public static final JetType NO_EXPECTED_TYPE = new SpecialType("NO_EXPECTED_TYPE");
086
087 public static final JetType UNIT_EXPECTED_TYPE = new SpecialType("UNIT_EXPECTED_TYPE");
088
089 public static boolean noExpectedType(@NotNull JetType type) {
090 return type == NO_EXPECTED_TYPE || type == UNIT_EXPECTED_TYPE;
091 }
092
093 @NotNull
094 public static JetType makeNullable(@NotNull JetType type) {
095 return makeNullableAsSpecified(type, true);
096 }
097
098 @NotNull
099 public static JetType makeNotNullable(@NotNull JetType type) {
100 return makeNullableAsSpecified(type, false);
101 }
102
103 @NotNull
104 public static JetType makeNullableAsSpecified(@NotNull JetType type, boolean nullable) {
105 if (type.isNullable() == nullable) {
106 return type;
107 }
108 if (ErrorUtils.isErrorType(type)) {
109 return type;
110 }
111 return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), nullable, type.getArguments(), type.getMemberScope());
112 }
113
114 public static boolean isIntersectionEmpty(@NotNull JetType typeA, @NotNull JetType typeB) {
115 return intersect(JetTypeChecker.INSTANCE, Sets.newLinkedHashSet(Lists.newArrayList(typeA, typeB))) == null;
116 }
117
118 @Nullable
119 public static JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set<JetType> types) {
120 if (types.isEmpty()) {
121 return KotlinBuiltIns.getInstance().getNullableAnyType();
122 }
123
124 if (types.size() == 1) {
125 return types.iterator().next();
126 }
127
128 // Intersection of T1..Tn is an intersection of their non-null versions,
129 // made nullable is they all were nullable
130 boolean allNullable = true;
131 boolean nothingTypePresent = false;
132 List<JetType> nullabilityStripped = Lists.newArrayList();
133 for (JetType type : types) {
134 nothingTypePresent |= KotlinBuiltIns.getInstance().isNothingOrNullableNothing(type);
135 allNullable &= type.isNullable();
136 nullabilityStripped.add(makeNotNullable(type));
137 }
138
139 if (nothingTypePresent) {
140 return allNullable ? KotlinBuiltIns.getInstance().getNullableNothingType() : KotlinBuiltIns.getInstance().getNothingType();
141 }
142
143 // Now we remove types that have subtypes in the list
144 List<JetType> resultingTypes = Lists.newArrayList();
145 outer:
146 for (JetType type : nullabilityStripped) {
147 if (!canHaveSubtypes(typeChecker, type)) {
148 for (JetType other : nullabilityStripped) {
149 // It makes sense to check for subtyping (other <: type), despite that
150 // type is not supposed to be open, for there're enums
151 if (!TypeUnifier.mayBeEqual(type, other) && !typeChecker.isSubtypeOf(type, other) && !typeChecker.isSubtypeOf(other, type)) {
152 return null;
153 }
154 }
155 return makeNullableAsSpecified(type, allNullable);
156 }
157 else {
158 for (JetType other : nullabilityStripped) {
159 if (!type.equals(other) && typeChecker.isSubtypeOf(other, type)) {
160 continue outer;
161 }
162
163 }
164 }
165
166 // Don't add type if it is already present, to avoid trivial type intersections in result
167 for (JetType other : resultingTypes) {
168 if (typeChecker.equalTypes(other, type)) {
169 continue outer;
170 }
171 }
172 resultingTypes.add(type);
173 }
174
175 if (resultingTypes.size() == 1) {
176 return makeNullableAsSpecified(resultingTypes.get(0), allNullable);
177 }
178
179
180 List<AnnotationDescriptor> noAnnotations = Collections.<AnnotationDescriptor>emptyList();
181 TypeConstructor constructor = new IntersectionTypeConstructor(
182 noAnnotations,
183 resultingTypes);
184
185 JetScope[] scopes = new JetScope[resultingTypes.size()];
186 int i = 0;
187 for (JetType type : resultingTypes) {
188 scopes[i] = type.getMemberScope();
189 i++;
190 }
191
192 return new JetTypeImpl(
193 noAnnotations,
194 constructor,
195 allNullable,
196 Collections.<TypeProjection>emptyList(),
197 new ChainedScope(null, scopes)); // TODO : check intersectibility, don't use a chanied scope
198 }
199
200 @NotNull
201 public static String toString(@NotNull JetType type) {
202 List<TypeProjection> arguments = type.getArguments();
203 return type.getConstructor() + (arguments.isEmpty() ? "" : "<" + argumentsToString(arguments) + ">") + (type.isNullable() ? "?" : "");
204 }
205
206 private static StringBuilder argumentsToString(List<TypeProjection> arguments) {
207 StringBuilder stringBuilder = new StringBuilder();
208 for (Iterator<TypeProjection> iterator = arguments.iterator(); iterator.hasNext();) {
209 TypeProjection argument = iterator.next();
210 stringBuilder.append(argument);
211 if (iterator.hasNext()) {
212 stringBuilder.append(", ");
213 }
214 }
215 return stringBuilder;
216 }
217
218 private static class TypeUnifier {
219 private static class TypeParameterUsage {
220 private final TypeParameterDescriptor typeParameterDescriptor;
221 private final Variance howTheTypeParameterIsUsed;
222
223 public TypeParameterUsage(TypeParameterDescriptor typeParameterDescriptor, Variance howTheTypeParameterIsUsed) {
224 this.typeParameterDescriptor = typeParameterDescriptor;
225 this.howTheTypeParameterIsUsed = howTheTypeParameterIsUsed;
226 }
227 }
228
229 public static boolean mayBeEqual(@NotNull JetType type, @NotNull JetType other) {
230 return unify(type, other);
231 }
232
233 private static boolean unify(JetType withParameters, JetType expected) {
234 ConstraintSystemWithPriorities constraintSystem = new ConstraintSystemWithPriorities(ConstraintResolutionListener.DO_NOTHING);
235 // T -> how T is used
236 final Map<TypeParameterDescriptor, Variance> parameters = Maps.newHashMap();
237 Processor<TypeParameterUsage> processor = new Processor<TypeParameterUsage>() {
238 @Override
239 public boolean process(TypeParameterUsage parameterUsage) {
240 Variance howTheTypeIsUsedBefore = parameters.get(parameterUsage.typeParameterDescriptor);
241 if (howTheTypeIsUsedBefore == null) {
242 howTheTypeIsUsedBefore = Variance.INVARIANT;
243 }
244 parameters.put(parameterUsage.typeParameterDescriptor,
245 parameterUsage.howTheTypeParameterIsUsed.superpose(howTheTypeIsUsedBefore));
246 return true;
247 }
248 };
249 processAllTypeParameters(withParameters, Variance.INVARIANT, processor);
250 processAllTypeParameters(expected, Variance.INVARIANT, processor);
251 for (Map.Entry<TypeParameterDescriptor, Variance> entry : parameters.entrySet()) {
252 constraintSystem.registerTypeVariable(entry.getKey(), entry.getValue());
253 }
254 constraintSystem.addSubtypingConstraint(ConstraintType.VALUE_ARGUMENT.assertSubtyping(withParameters, expected));
255
256 ConstraintSystemSolution solution = constraintSystem.solve();
257 return solution.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().isSealed()) {
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 return makeUnsubstitutedType(classDescriptor.getTypeConstructor(), unsubstitutedMemberScope);
357 }
358
359 @NotNull
360 public static JetType makeUnsubstitutedType(TypeConstructor typeConstructor, JetScope unsubstitutedMemberScope) {
361 if (ErrorUtils.isError(typeConstructor)) {
362 return ErrorUtils.createErrorType("Unsubstituted type for " + typeConstructor);
363 }
364 List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
365 return new JetTypeImpl(
366 Collections.<AnnotationDescriptor>emptyList(),
367 typeConstructor,
368 false,
369 arguments,
370 unsubstitutedMemberScope
371 );
372 }
373
374 @NotNull
375 public static List<TypeProjection> getDefaultTypeProjections(List<TypeParameterDescriptor> parameters) {
376 List<TypeProjection> result = new ArrayList<TypeProjection>();
377 for (TypeParameterDescriptor parameterDescriptor : parameters) {
378 result.add(new TypeProjection(parameterDescriptor.getDefaultType()));
379 }
380 return result;
381 }
382
383 @NotNull
384 public static List<JetType> getDefaultTypes(List<TypeParameterDescriptor> parameters) {
385 List<JetType> result = Lists.newArrayList();
386 for (TypeParameterDescriptor parameterDescriptor : parameters) {
387 result.add(parameterDescriptor.getDefaultType());
388 }
389 return result;
390 }
391
392 private static void collectImmediateSupertypes(@NotNull JetType type, @NotNull Collection<JetType> result) {
393 TypeSubstitutor substitutor = TypeSubstitutor.create(type);
394 for (JetType supertype : type.getConstructor().getSupertypes()) {
395 result.add(substitutor.substitute(supertype, Variance.INVARIANT));
396 }
397 }
398
399 @NotNull
400 public static List<JetType> getImmediateSupertypes(@NotNull JetType type) {
401 List<JetType> result = Lists.newArrayList();
402 collectImmediateSupertypes(type, result);
403 return result;
404 }
405
406 private static void collectAllSupertypes(@NotNull JetType type, @NotNull Set<JetType> result) {
407 List<JetType> immediateSupertypes = getImmediateSupertypes(type);
408 result.addAll(immediateSupertypes);
409 for (JetType supertype : immediateSupertypes) {
410 collectAllSupertypes(supertype, result);
411 }
412 }
413
414
415 @NotNull
416 public static Set<JetType> getAllSupertypes(@NotNull JetType type) {
417 // 15 is obtained by experimentation: JDK classes like ArrayList tend to have so many supertypes,
418 // the average number is lower
419 Set<JetType> result = new LinkedHashSet<JetType>(15);
420 collectAllSupertypes(type, result);
421 return result;
422 }
423
424 public static boolean hasNullableLowerBound(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
425 for (JetType bound : typeParameterDescriptor.getLowerBounds()) {
426 if (bound.isNullable()) {
427 return true;
428 }
429 }
430 return false;
431 }
432
433 public static boolean hasNullableSuperType(@NotNull JetType type) {
434 if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
435 // A class/trait cannot have a nullable supertype
436 return false;
437 }
438
439 for (JetType supertype : getImmediateSupertypes(type)) {
440 if (supertype.isNullable()) return true;
441 if (hasNullableSuperType(supertype)) return true;
442 }
443
444 return false;
445 }
446
447 public static boolean equalClasses(@NotNull JetType type1, @NotNull JetType type2) {
448 DeclarationDescriptor declarationDescriptor1 = type1.getConstructor().getDeclarationDescriptor();
449 if (declarationDescriptor1 == null) return false; // No class, classes are not equal
450 DeclarationDescriptor declarationDescriptor2 = type2.getConstructor().getDeclarationDescriptor();
451 if (declarationDescriptor2 == null) return false; // Class of type1 is not null
452 return declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal());
453 }
454
455 @Nullable
456 public static ClassDescriptor getClassDescriptor(@NotNull JetType type) {
457 DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
458 if (declarationDescriptor instanceof ClassDescriptor) {
459 return (ClassDescriptor) declarationDescriptor;
460 }
461 return null;
462 }
463
464 @NotNull
465 public static JetType substituteParameters(@NotNull ClassDescriptor clazz, @NotNull List<JetType> typeArguments) {
466 List<TypeProjection> projections = ContainerUtil.map(typeArguments, new com.intellij.util.Function<JetType, TypeProjection>() {
467 @Override
468 public TypeProjection fun(JetType type) {
469 return new TypeProjection(type);
470 }
471 });
472
473 return substituteProjectionsForParameters(clazz, projections);
474 }
475
476 @NotNull
477 public static JetType substituteProjectionsForParameters(@NotNull ClassDescriptor clazz, @NotNull List<TypeProjection> projections) {
478 List<TypeParameterDescriptor> clazzTypeParameters = clazz.getTypeConstructor().getParameters();
479 if (clazzTypeParameters.size() != projections.size()) {
480 throw new IllegalArgumentException("type parameter counts do not match: " + clazz + ", " + projections);
481 }
482
483 Map<TypeConstructor, TypeProjection> substitutions = Maps.newHashMap();
484
485 for (int i = 0; i < clazzTypeParameters.size(); ++i) {
486 TypeConstructor typeConstructor = clazzTypeParameters.get(i).getTypeConstructor();
487 substitutions.put(typeConstructor, projections.get(i));
488 }
489
490 return TypeSubstitutor.create(substitutions).substitute(clazz.getDefaultType(), Variance.INVARIANT);
491 }
492
493 private static void addAllClassDescriptors(@NotNull JetType type, @NotNull Set<ClassDescriptor> set) {
494 ClassDescriptor cd = getClassDescriptor(type);
495 if (cd != null) {
496 set.add(cd);
497 }
498 for (TypeProjection projection : type.getArguments()) {
499 addAllClassDescriptors(projection.getType(), set);
500 }
501 }
502
503 @NotNull
504 public static List<ClassDescriptor> getAllClassDescriptors(@NotNull JetType type) {
505 Set<ClassDescriptor> classDescriptors = new HashSet<ClassDescriptor>();
506 addAllClassDescriptors(type, classDescriptors);
507 return new ArrayList<ClassDescriptor>(classDescriptors);
508 }
509
510 public static boolean equalTypes(@NotNull JetType a, @NotNull JetType b) {
511 return JetTypeChecker.INSTANCE.isSubtypeOf(a, b) && JetTypeChecker.INSTANCE.isSubtypeOf(b, a);
512 }
513
514 public static boolean typeConstructorUsedInType(@NotNull TypeConstructor key, @NotNull JetType value) {
515 if (value.getConstructor() == key) return true;
516 for (TypeProjection projection : value.getArguments()) {
517 if (typeConstructorUsedInType(key, projection.getType())) {
518 return true;
519 }
520 }
521 return false;
522 }
523
524 public static boolean dependsOnTypeParameters(@NotNull JetType type, @NotNull Collection<TypeParameterDescriptor> typeParameters) {
525 return dependsOnTypeConstructors(type, Collections2
526 .transform(typeParameters, new Function<TypeParameterDescriptor, TypeConstructor>() {
527 @Override
528 public TypeConstructor apply(@Nullable TypeParameterDescriptor typeParameterDescriptor) {
529 assert typeParameterDescriptor != null;
530 return typeParameterDescriptor.getTypeConstructor();
531 }
532 }));
533 }
534
535 public static boolean dependsOnTypeConstructors(@NotNull JetType type, @NotNull Collection<TypeConstructor> typeParameterConstructors) {
536 if (typeParameterConstructors.contains(type.getConstructor())) return true;
537 for (TypeProjection typeProjection : type.getArguments()) {
538 if (dependsOnTypeConstructors(typeProjection.getType(), typeParameterConstructors)) {
539 return true;
540 }
541 }
542 return false;
543 }
544
545 public static boolean equalsOrContainsAsArgument(@Nullable JetType type, @NotNull JetType... possibleArgumentTypes) {
546 return equalsOrContainsAsArgument(type, Sets.newHashSet(possibleArgumentTypes));
547 }
548
549 private static boolean equalsOrContainsAsArgument(@Nullable JetType type, @NotNull Set<JetType> possibleArgumentTypes) {
550 if (type == null) return false;
551 if (possibleArgumentTypes.contains(type)) return true;
552 if (type instanceof NamespaceType) return false;
553 for (TypeProjection projection : type.getArguments()) {
554 if (equalsOrContainsAsArgument(projection.getType(), possibleArgumentTypes)) return true;
555 }
556 return false;
557 }
558
559 @NotNull
560 public static String getTypeNameAndStarProjectionsString(@NotNull String name, int size) {
561 StringBuilder builder = new StringBuilder(name);
562 builder.append("<");
563 for (int i = 0; i < size; i++) {
564 builder.append("*");
565 if (i == size - 1) break;
566 builder.append(", ");
567 }
568 builder.append(">");
569
570 return builder.toString();
571 }
572
573 @NotNull
574 public static JetType commonSupertypeForNumberTypes(@NotNull Collection<JetType> numberLowerBounds) {
575 assert !numberLowerBounds.isEmpty();
576 Set<JetType> intersectionOfSupertypes = getIntersectionOfSupertypes(numberLowerBounds);
577 JetType primitiveNumberType = getDefaultPrimitiveNumberType(intersectionOfSupertypes);
578 if (primitiveNumberType != null) {
579 return primitiveNumberType;
580 }
581 return CommonSupertypes.commonSupertype(numberLowerBounds);
582 }
583
584 @NotNull
585 private static Set<JetType> getIntersectionOfSupertypes(@NotNull Collection<JetType> types) {
586 Set<JetType> upperBounds = Sets.newHashSet();
587 for (JetType type : types) {
588 Set<JetType> supertypes = Sets.newHashSet(type.getConstructor().getSupertypes());
589 if (upperBounds.isEmpty()) {
590 upperBounds.addAll(supertypes);
591 }
592 else {
593 upperBounds = Sets.intersection(upperBounds, supertypes);
594 }
595 }
596 return upperBounds;
597 }
598
599 @NotNull
600 public static JetType getDefaultPrimitiveNumberType(@NotNull NumberValueTypeConstructor numberValueTypeConstructor) {
601 JetType type = getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
602 assert type != null : "Strange number value type constructor: " + numberValueTypeConstructor + ". " +
603 "Super types doesn't contain double, int or long: " + numberValueTypeConstructor.getSupertypes();
604 return type;
605 }
606
607 @Nullable
608 private static JetType getDefaultPrimitiveNumberType(@NotNull Collection<JetType> supertypes) {
609 JetType doubleType = KotlinBuiltIns.getInstance().getDoubleType();
610 if (supertypes.contains(doubleType)) {
611 return doubleType;
612 }
613 JetType intType = KotlinBuiltIns.getInstance().getIntType();
614 if (supertypes.contains(intType)) {
615 return intType;
616 }
617 JetType longType = KotlinBuiltIns.getInstance().getLongType();
618 if (supertypes.contains(longType)) {
619 return longType;
620 }
621 return null;
622 }
623
624 @NotNull
625 public static JetType getPrimitiveNumberType(
626 @NotNull NumberValueTypeConstructor numberValueTypeConstructor,
627 @NotNull JetType expectedType
628 ) {
629 if (noExpectedType(expectedType) || ErrorUtils.isErrorType(expectedType)) {
630 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
631 }
632 for (JetType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) {
633 if (JetTypeChecker.INSTANCE.isSubtypeOf(primitiveNumberType, expectedType)) {
634 return primitiveNumberType;
635 }
636 }
637 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
638 }
639
640 @NotNull
641 public static Pair<Collection<JetType>, Collection<JetType>> filterNumberTypes(@NotNull Collection<JetType> types) {
642 Collection<JetType> numberTypes = Sets.newLinkedHashSet();
643 Collection<JetType> otherTypes = Sets.newLinkedHashSet();
644 for (JetType type : types) {
645 if (type.getConstructor() instanceof NumberValueTypeConstructor) {
646 numberTypes.add(type);
647 }
648 else {
649 otherTypes.add(type);
650 }
651 }
652 return Pair.create(otherTypes, numberTypes);
653 }
654 }