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.collections.CollectionsKt;
020 import kotlin.jvm.functions.Function1;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
024 import org.jetbrains.kotlin.descriptors.ClassDescriptor;
025 import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
026 import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
027 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
028 import org.jetbrains.kotlin.resolve.calls.inference.CapturedType;
029 import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructor;
030 import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor;
031 import org.jetbrains.kotlin.resolve.scopes.MemberScope;
032 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
033 import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
034
035 import java.util.*;
036
037 public class TypeUtils {
038 public static final KotlinType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
039 public static final KotlinType CANT_INFER_FUNCTION_PARAM_TYPE = ErrorUtils.createErrorType("Cannot be inferred");
040
041 public static class SpecialType implements KotlinType {
042 private final String name;
043
044 public SpecialType(String name) {
045 this.name = name;
046 }
047
048 @NotNull
049 @Override
050 public TypeConstructor getConstructor() {
051 throw new IllegalStateException(name);
052 }
053
054 @NotNull
055 @Override
056 public List<TypeProjection> getArguments() {
057 throw new IllegalStateException(name);
058 }
059
060 @NotNull
061 @Override
062 public TypeSubstitution getSubstitution() {
063 throw new IllegalStateException(name);
064 }
065
066 @Override
067 public boolean isMarkedNullable() {
068 throw new IllegalStateException(name);
069 }
070
071 @NotNull
072 @Override
073 public MemberScope getMemberScope() {
074 throw new IllegalStateException(name);
075 }
076
077 @Override
078 public boolean isError() {
079 return false;
080 }
081
082 @NotNull
083 @Override
084 public Annotations getAnnotations() {
085 throw new IllegalStateException(name);
086 }
087
088 @Nullable
089 @Override
090 public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
091 return null;
092 }
093
094 @NotNull
095 @Override
096 public TypeCapabilities getCapabilities() {
097 return TypeCapabilities.NONE.INSTANCE;
098 }
099
100 @Override
101 public String toString() {
102 return name;
103 }
104 }
105
106 @NotNull
107 public static final KotlinType NO_EXPECTED_TYPE = new SpecialType("NO_EXPECTED_TYPE");
108
109 public static final KotlinType UNIT_EXPECTED_TYPE = new SpecialType("UNIT_EXPECTED_TYPE");
110
111 public static boolean noExpectedType(@NotNull KotlinType type) {
112 return type == NO_EXPECTED_TYPE || type == UNIT_EXPECTED_TYPE;
113 }
114
115 public static boolean isDontCarePlaceholder(@Nullable KotlinType type) {
116 return type != null && type.getConstructor() == DONT_CARE.getConstructor();
117 }
118
119 @NotNull
120 public static KotlinType makeNullable(@NotNull KotlinType type) {
121 return makeNullableAsSpecified(type, true);
122 }
123
124 @NotNull
125 public static KotlinType makeNotNullable(@NotNull KotlinType type) {
126 return makeNullableAsSpecified(type, false);
127 }
128
129 @NotNull
130 public static KotlinType makeNullableAsSpecified(@NotNull KotlinType type, boolean nullable) {
131 NullAwareness nullAwareness = type.getCapability(NullAwareness.class);
132 if (nullAwareness != null) {
133 return nullAwareness.makeNullableAsSpecified(nullable);
134 }
135
136 // Wrapping serves two purposes here
137 // 1. It's requires less memory than copying with a changed nullability flag: a copy has many fields, while a wrapper has only one
138 // 2. It preserves laziness of types
139
140 // Unwrap to avoid long delegation call chains
141 if (type instanceof AbstractTypeWithKnownNullability) {
142 return makeNullableAsSpecified(((AbstractTypeWithKnownNullability) type).delegate, nullable);
143 }
144
145 // checking to preserve laziness
146 if (!(type instanceof LazyType) && type.isMarkedNullable() == nullable) {
147 return type;
148 }
149
150 return nullable ? new NullableType(type) : new NotNullType(type);
151 }
152
153 @NotNull
154 public static KotlinType makeNullableIfNeeded(@NotNull KotlinType type, boolean nullable) {
155 if (nullable) {
156 return makeNullable(type);
157 }
158 return type;
159 }
160
161 public static boolean canHaveSubtypes(KotlinTypeChecker typeChecker, @NotNull KotlinType type) {
162 if (type.isMarkedNullable()) {
163 return true;
164 }
165 if (!type.getConstructor().isFinal()) {
166 return true;
167 }
168
169 List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
170 List<TypeProjection> arguments = type.getArguments();
171 for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
172 TypeParameterDescriptor parameterDescriptor = parameters.get(i);
173 TypeProjection typeProjection = arguments.get(i);
174 Variance projectionKind = typeProjection.getProjectionKind();
175 KotlinType argument = typeProjection.getType();
176
177 switch (parameterDescriptor.getVariance()) {
178 case INVARIANT:
179 switch (projectionKind) {
180 case INVARIANT:
181 if (lowerThanBound(typeChecker, argument, parameterDescriptor) || canHaveSubtypes(typeChecker, argument)) {
182 return true;
183 }
184 break;
185 case IN_VARIANCE:
186 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
187 return true;
188 }
189 break;
190 case OUT_VARIANCE:
191 if (canHaveSubtypes(typeChecker, argument)) {
192 return true;
193 }
194 break;
195 }
196 break;
197 case IN_VARIANCE:
198 if (projectionKind != Variance.OUT_VARIANCE) {
199 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
200 return true;
201 }
202 }
203 else {
204 if (canHaveSubtypes(typeChecker, argument)) {
205 return true;
206 }
207 }
208 break;
209 case OUT_VARIANCE:
210 if (projectionKind != Variance.IN_VARIANCE) {
211 if (canHaveSubtypes(typeChecker, argument)) {
212 return true;
213 }
214 }
215 else {
216 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
217 return true;
218 }
219 }
220 break;
221 }
222 }
223 return false;
224 }
225
226 private static boolean lowerThanBound(KotlinTypeChecker typeChecker, KotlinType argument, TypeParameterDescriptor parameterDescriptor) {
227 for (KotlinType bound : parameterDescriptor.getUpperBounds()) {
228 if (typeChecker.isSubtypeOf(argument, bound)) {
229 if (!argument.getConstructor().equals(bound.getConstructor())) {
230 return true;
231 }
232 }
233 }
234 return false;
235 }
236
237 @NotNull
238 public static KotlinType makeUnsubstitutedType(ClassDescriptor classDescriptor, MemberScope unsubstitutedMemberScope) {
239 if (ErrorUtils.isError(classDescriptor)) {
240 return ErrorUtils.createErrorType("Unsubstituted type for " + classDescriptor);
241 }
242 TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
243 List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
244 return KotlinTypeImpl.create(
245 Annotations.Companion.getEMPTY(),
246 typeConstructor,
247 false,
248 arguments,
249 unsubstitutedMemberScope
250 );
251 }
252
253 @NotNull
254 public static List<TypeProjection> getDefaultTypeProjections(@NotNull List<TypeParameterDescriptor> parameters) {
255 List<TypeProjection> result = new ArrayList<TypeProjection>(parameters.size());
256 for (TypeParameterDescriptor parameterDescriptor : parameters) {
257 result.add(new TypeProjectionImpl(parameterDescriptor.getDefaultType()));
258 }
259 return org.jetbrains.kotlin.utils.CollectionsKt.toReadOnlyList(result);
260 }
261
262 @NotNull
263 public static List<KotlinType> getImmediateSupertypes(@NotNull KotlinType type) {
264 TypeSubstitutor substitutor = TypeSubstitutor.create(type);
265 Collection<KotlinType> originalSupertypes = type.getConstructor().getSupertypes();
266 List<KotlinType> result = new ArrayList<KotlinType>(originalSupertypes.size());
267 for (KotlinType supertype : originalSupertypes) {
268 KotlinType substitutedType = createSubstitutedSupertype(type, supertype, substitutor);
269 if (substitutedType != null) {
270 result.add(substitutedType);
271 }
272 }
273 return result;
274 }
275
276 @Nullable
277 public static KotlinType createSubstitutedSupertype(
278 @NotNull KotlinType subType,
279 @NotNull KotlinType superType,
280 @NotNull TypeSubstitutor substitutor
281 ) {
282 KotlinType substitutedType = substitutor.substitute(superType, Variance.INVARIANT);
283 if (substitutedType != null) {
284 return makeNullableIfNeeded(substitutedType, subType.isMarkedNullable());
285 }
286 return null;
287 }
288
289 private static void collectAllSupertypes(@NotNull KotlinType type, @NotNull Set<KotlinType> result) {
290 List<KotlinType> immediateSupertypes = getImmediateSupertypes(type);
291 result.addAll(immediateSupertypes);
292 for (KotlinType supertype : immediateSupertypes) {
293 collectAllSupertypes(supertype, result);
294 }
295 }
296
297
298 @NotNull
299 public static Set<KotlinType> getAllSupertypes(@NotNull KotlinType type) {
300 // 15 is obtained by experimentation: JDK classes like ArrayList tend to have so many supertypes,
301 // the average number is lower
302 Set<KotlinType> result = new LinkedHashSet<KotlinType>(15);
303 collectAllSupertypes(type, result);
304 return result;
305 }
306
307 /**
308 * A work-around of the generic nullability problem in the type checker
309 * Semantics should be the same as `!isSubtype(T, Any)`
310 * @return true if a value of this type can be null
311 */
312 public static boolean isNullableType(@NotNull KotlinType type) {
313 if (type.isMarkedNullable()) {
314 return true;
315 }
316 if (FlexibleTypesKt.isFlexible(type) && isNullableType(FlexibleTypesKt.flexibility(type).getUpperBound())) {
317 return true;
318 }
319 if (isTypeParameter(type)) {
320 return hasNullableSuperType(type);
321 }
322 return false;
323 }
324
325 /**
326 * Differs from `isNullableType` only by treating type parameters: acceptsNullable(T) <=> T has nullable lower bound
327 * Semantics should be the same as `isSubtype(Nothing?, T)`
328 * @return true if `null` can be assigned to storage of this type
329 */
330 public static boolean acceptsNullable(@NotNull KotlinType type) {
331 if (type.isMarkedNullable()) {
332 return true;
333 }
334 if (FlexibleTypesKt.isFlexible(type) && acceptsNullable(FlexibleTypesKt.flexibility(type).getUpperBound())) {
335 return true;
336 }
337 return false;
338 }
339
340 public static boolean hasNullableSuperType(@NotNull KotlinType type) {
341 if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
342 // A class/trait cannot have a nullable supertype
343 return false;
344 }
345
346 for (KotlinType supertype : getImmediateSupertypes(type)) {
347 if (supertype.isMarkedNullable()) return true;
348 if (hasNullableSuperType(supertype)) return true;
349 }
350
351 return false;
352 }
353
354 @Nullable
355 public static ClassDescriptor getClassDescriptor(@NotNull KotlinType type) {
356 DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
357 if (declarationDescriptor instanceof ClassDescriptor) {
358 return (ClassDescriptor) declarationDescriptor;
359 }
360 return null;
361 }
362
363 @NotNull
364 public static KotlinType substituteParameters(@NotNull ClassDescriptor clazz, @NotNull List<KotlinType> typeArguments) {
365 List<TypeProjection> projections = CollectionsKt.map(typeArguments, new Function1<KotlinType, TypeProjection>() {
366 @Override
367 public TypeProjection invoke(KotlinType type) {
368 return new TypeProjectionImpl(type);
369 }
370 });
371
372 return substituteProjectionsForParameters(clazz, projections);
373 }
374
375 @NotNull
376 public static KotlinType substituteProjectionsForParameters(@NotNull ClassDescriptor clazz, @NotNull List<TypeProjection> projections) {
377 List<TypeParameterDescriptor> clazzTypeParameters = clazz.getTypeConstructor().getParameters();
378 if (clazzTypeParameters.size() != projections.size()) {
379 throw new IllegalArgumentException("type parameter counts do not match: " + clazz + ", " + projections);
380 }
381
382 Map<TypeConstructor, TypeProjection> substitutions = org.jetbrains.kotlin.utils.CollectionsKt
383 .newHashMapWithExpectedSize(clazzTypeParameters.size());
384
385 for (int i = 0; i < clazzTypeParameters.size(); ++i) {
386 TypeConstructor typeConstructor = clazzTypeParameters.get(i).getTypeConstructor();
387 substitutions.put(typeConstructor, projections.get(i));
388 }
389
390 return TypeSubstitutor.create(substitutions).substitute(clazz.getDefaultType(), Variance.INVARIANT);
391 }
392
393 public static boolean equalTypes(@NotNull KotlinType a, @NotNull KotlinType b) {
394 return KotlinTypeChecker.DEFAULT.isSubtypeOf(a, b) && KotlinTypeChecker.DEFAULT.isSubtypeOf(b, a);
395 }
396
397 public static boolean dependsOnTypeParameters(@NotNull KotlinType type, @NotNull Collection<TypeParameterDescriptor> typeParameters) {
398 return dependsOnTypeConstructors(type, CollectionsKt.map(
399 typeParameters,
400 new Function1<TypeParameterDescriptor, TypeConstructor>() {
401 @Override
402 public TypeConstructor invoke(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
403 return typeParameterDescriptor.getTypeConstructor();
404 }
405 }
406 ));
407 }
408
409 public static boolean dependsOnTypeConstructors(@NotNull KotlinType type, @NotNull Collection<TypeConstructor> typeParameterConstructors) {
410 if (typeParameterConstructors.contains(type.getConstructor())) return true;
411 for (TypeProjection typeProjection : type.getArguments()) {
412 if (!typeProjection.isStarProjection() && dependsOnTypeConstructors(typeProjection.getType(), typeParameterConstructors)) {
413 return true;
414 }
415 }
416 return false;
417 }
418
419 public static boolean contains(@Nullable KotlinType type, @NotNull final KotlinType specialType) {
420 return contains(type, new Function1<KotlinType, Boolean>() {
421 @Override
422 public Boolean invoke(KotlinType type) {
423 return specialType.equals(type);
424 }
425 });
426 }
427
428 public static boolean contains(
429 @Nullable KotlinType type,
430 @NotNull Function1<KotlinType, Boolean> isSpecialType
431 ) {
432 if (type == null) return false;
433 if (isSpecialType.invoke(type)) return true;
434 Flexibility flexibility = type.getCapability(Flexibility.class);
435 if (flexibility != null
436 && (contains(flexibility.getLowerBound(), isSpecialType) || contains(flexibility.getUpperBound(), isSpecialType))) {
437 return true;
438 }
439 for (TypeProjection projection : type.getArguments()) {
440 if (!projection.isStarProjection() && contains(projection.getType(), isSpecialType)) return true;
441 }
442 return false;
443 }
444
445 @NotNull
446 public static TypeProjection makeStarProjection(@NotNull TypeParameterDescriptor parameterDescriptor) {
447 return new StarProjectionImpl(parameterDescriptor);
448 }
449
450 @NotNull
451 public static KotlinType getDefaultPrimitiveNumberType(@NotNull IntegerValueTypeConstructor numberValueTypeConstructor) {
452 KotlinType type = getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
453 assert type != null : "Strange number value type constructor: " + numberValueTypeConstructor + ". " +
454 "Super types doesn't contain double, int or long: " + numberValueTypeConstructor.getSupertypes();
455 return type;
456 }
457
458 @Nullable
459 public static KotlinType getDefaultPrimitiveNumberType(@NotNull Collection<KotlinType> supertypes) {
460 if (supertypes.isEmpty()) {
461 return null;
462 }
463
464 KotlinBuiltIns builtIns = supertypes.iterator().next().getConstructor().getBuiltIns();
465 KotlinType doubleType = builtIns.getDoubleType();
466 if (supertypes.contains(doubleType)) {
467 return doubleType;
468 }
469 KotlinType intType = builtIns.getIntType();
470 if (supertypes.contains(intType)) {
471 return intType;
472 }
473 KotlinType longType = builtIns.getLongType();
474 if (supertypes.contains(longType)) {
475 return longType;
476 }
477 return null;
478 }
479
480 @NotNull
481 public static KotlinType getPrimitiveNumberType(
482 @NotNull IntegerValueTypeConstructor numberValueTypeConstructor,
483 @NotNull KotlinType expectedType
484 ) {
485 if (noExpectedType(expectedType) || expectedType.isError()) {
486 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
487 }
488 for (KotlinType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) {
489 if (KotlinTypeChecker.DEFAULT.isSubtypeOf(primitiveNumberType, expectedType)) {
490 return primitiveNumberType;
491 }
492 }
493 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
494 }
495
496 public static boolean isTypeParameter(@NotNull KotlinType type) {
497 return getTypeParameterDescriptorOrNull(type) != null;
498 }
499
500 public static boolean isNonReifiedTypeParemeter(@NotNull KotlinType type) {
501 TypeParameterDescriptor typeParameterDescriptor = getTypeParameterDescriptorOrNull(type);
502 return typeParameterDescriptor != null && !typeParameterDescriptor.isReified();
503 }
504
505 public static boolean isReifiedTypeParameter(@NotNull KotlinType type) {
506 TypeParameterDescriptor typeParameterDescriptor = getTypeParameterDescriptorOrNull(type);
507 return typeParameterDescriptor != null && typeParameterDescriptor.isReified();
508 }
509
510 @NotNull
511 public static KotlinType uncaptureTypeForInlineMapping(@NotNull KotlinType type) {
512 TypeConstructor constructor = type.getConstructor();
513 if (constructor instanceof CapturedTypeConstructor) {
514 TypeProjection projection = ((CapturedTypeConstructor) constructor).getTypeProjection();
515 if (Variance.IN_VARIANCE == projection.getProjectionKind()) {
516 //in variance could be captured only for <T> or <T: Any?> declarations
517 return TypeUtilsKt.getBuiltIns(type).getNullableAnyType();
518 }
519 return uncaptureTypeForInlineMapping(projection.getType());
520 }
521 return type;
522 }
523 @Nullable
524 public static TypeParameterDescriptor getTypeParameterDescriptorOrNull(@NotNull KotlinType type) {
525 assert !(type instanceof CapturedType) : "Type should be non-captured " + type;
526 if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
527 return (TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor();
528 }
529 return null;
530 }
531
532 private static abstract class AbstractTypeWithKnownNullability extends AbstractKotlinType {
533 private final KotlinType delegate;
534
535 private AbstractTypeWithKnownNullability(@NotNull KotlinType delegate) {
536 this.delegate = delegate;
537 }
538
539 @Override
540 @NotNull
541 public TypeConstructor getConstructor() {
542 return delegate.getConstructor();
543 }
544
545 @Override
546 @NotNull
547 public List<TypeProjection> getArguments() {
548 return delegate.getArguments();
549 }
550
551 @Override
552 public abstract boolean isMarkedNullable();
553
554 @Override
555 @NotNull
556 public MemberScope getMemberScope() {
557 return delegate.getMemberScope();
558 }
559
560 @Override
561 public boolean isError() {
562 return delegate.isError();
563 }
564
565 @Override
566 @NotNull
567 public Annotations getAnnotations() {
568 return delegate.getAnnotations();
569 }
570
571 @NotNull
572 @Override
573 public TypeSubstitution getSubstitution() {
574 return delegate.getSubstitution();
575 }
576
577 @Nullable
578 @Override
579 public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
580 return delegate.getCapability(capabilityClass);
581 }
582
583 @NotNull
584 @Override
585 public TypeCapabilities getCapabilities() {
586 return delegate.getCapabilities();
587 }
588 }
589
590 private static class NullableType extends AbstractTypeWithKnownNullability {
591
592 private NullableType(@NotNull KotlinType delegate) {
593 super(delegate);
594 }
595
596 @Override
597 public boolean isMarkedNullable() {
598 return true;
599 }
600 }
601
602 private static class NotNullType extends AbstractTypeWithKnownNullability {
603
604 private NotNullType(@NotNull KotlinType delegate) {
605 super(delegate);
606 }
607
608 @Override
609 public boolean isMarkedNullable() {
610 return false;
611 }
612 }
613
614 }