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.constants.IntegerValueTypeConstructor;
030 import org.jetbrains.kotlin.resolve.scopes.MemberScope;
031 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
032
033 import java.util.*;
034
035 public class TypeUtils {
036 public static final KotlinType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
037 public static final KotlinType CANT_INFER_FUNCTION_PARAM_TYPE = ErrorUtils.createErrorType("Cannot be inferred");
038
039 public static class SpecialType implements KotlinType {
040 private final String name;
041
042 public SpecialType(String name) {
043 this.name = name;
044 }
045
046 @NotNull
047 @Override
048 public TypeConstructor getConstructor() {
049 throw new IllegalStateException(name);
050 }
051
052 @NotNull
053 @Override
054 public List<TypeProjection> getArguments() {
055 throw new IllegalStateException(name);
056 }
057
058 @NotNull
059 @Override
060 public TypeSubstitution getSubstitution() {
061 throw new IllegalStateException(name);
062 }
063
064 @Override
065 public boolean isMarkedNullable() {
066 throw new IllegalStateException(name);
067 }
068
069 @NotNull
070 @Override
071 public MemberScope getMemberScope() {
072 throw new IllegalStateException(name);
073 }
074
075 @Override
076 public boolean isError() {
077 return false;
078 }
079
080 @NotNull
081 @Override
082 public Annotations getAnnotations() {
083 throw new IllegalStateException(name);
084 }
085
086 @Nullable
087 @Override
088 public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
089 return null;
090 }
091
092 @NotNull
093 @Override
094 public TypeCapabilities getCapabilities() {
095 return TypeCapabilities.NONE.INSTANCE;
096 }
097
098 @Override
099 public String toString() {
100 return name;
101 }
102 }
103
104 @NotNull
105 public static final KotlinType NO_EXPECTED_TYPE = new SpecialType("NO_EXPECTED_TYPE");
106
107 public static final KotlinType UNIT_EXPECTED_TYPE = new SpecialType("UNIT_EXPECTED_TYPE");
108
109 public static boolean noExpectedType(@NotNull KotlinType type) {
110 return type == NO_EXPECTED_TYPE || type == UNIT_EXPECTED_TYPE;
111 }
112
113 public static boolean isDontCarePlaceholder(@Nullable KotlinType type) {
114 return type != null && type.getConstructor() == DONT_CARE.getConstructor();
115 }
116
117 @NotNull
118 public static KotlinType makeNullable(@NotNull KotlinType type) {
119 return makeNullableAsSpecified(type, true);
120 }
121
122 @NotNull
123 public static KotlinType makeNotNullable(@NotNull KotlinType type) {
124 return makeNullableAsSpecified(type, false);
125 }
126
127 @NotNull
128 public static KotlinType makeNullableAsSpecified(@NotNull KotlinType type, boolean nullable) {
129 NullAwareness nullAwareness = type.getCapability(NullAwareness.class);
130 if (nullAwareness != null) {
131 return nullAwareness.makeNullableAsSpecified(nullable);
132 }
133
134 // Wrapping serves two purposes here
135 // 1. It's requires less memory than copying with a changed nullability flag: a copy has many fields, while a wrapper has only one
136 // 2. It preserves laziness of types
137
138 // Unwrap to avoid long delegation call chains
139 if (type instanceof AbstractTypeWithKnownNullability) {
140 return makeNullableAsSpecified(((AbstractTypeWithKnownNullability) type).delegate, nullable);
141 }
142
143 // checking to preserve laziness
144 if (!(type instanceof LazyType) && type.isMarkedNullable() == nullable) {
145 return type;
146 }
147
148 return nullable ? new NullableType(type) : new NotNullType(type);
149 }
150
151 @NotNull
152 public static KotlinType makeNullableIfNeeded(@NotNull KotlinType type, boolean nullable) {
153 if (nullable) {
154 return makeNullable(type);
155 }
156 return type;
157 }
158
159 public static boolean canHaveSubtypes(KotlinTypeChecker typeChecker, @NotNull KotlinType type) {
160 if (type.isMarkedNullable()) {
161 return true;
162 }
163 if (!type.getConstructor().isFinal()) {
164 return true;
165 }
166
167 List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
168 List<TypeProjection> arguments = type.getArguments();
169 for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
170 TypeParameterDescriptor parameterDescriptor = parameters.get(i);
171 TypeProjection typeProjection = arguments.get(i);
172 if (typeProjection.isStarProjection()) return true;
173
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 @Nullable
511 public static TypeParameterDescriptor getTypeParameterDescriptorOrNull(@NotNull KotlinType type) {
512 if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
513 return (TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor();
514 }
515 return null;
516 }
517
518 private static abstract class AbstractTypeWithKnownNullability extends AbstractKotlinType {
519 private final KotlinType delegate;
520
521 private AbstractTypeWithKnownNullability(@NotNull KotlinType delegate) {
522 this.delegate = delegate;
523 }
524
525 @Override
526 @NotNull
527 public TypeConstructor getConstructor() {
528 return delegate.getConstructor();
529 }
530
531 @Override
532 @NotNull
533 public List<TypeProjection> getArguments() {
534 return delegate.getArguments();
535 }
536
537 @Override
538 public abstract boolean isMarkedNullable();
539
540 @Override
541 @NotNull
542 public MemberScope getMemberScope() {
543 return delegate.getMemberScope();
544 }
545
546 @Override
547 public boolean isError() {
548 return delegate.isError();
549 }
550
551 @Override
552 @NotNull
553 public Annotations getAnnotations() {
554 return delegate.getAnnotations();
555 }
556
557 @NotNull
558 @Override
559 public TypeSubstitution getSubstitution() {
560 return delegate.getSubstitution();
561 }
562
563 @Nullable
564 @Override
565 public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
566 return delegate.getCapability(capabilityClass);
567 }
568
569 @NotNull
570 @Override
571 public TypeCapabilities getCapabilities() {
572 return delegate.getCapabilities();
573 }
574 }
575
576 private static class NullableType extends AbstractTypeWithKnownNullability {
577
578 private NullableType(@NotNull KotlinType delegate) {
579 super(delegate);
580 }
581
582 @Override
583 public boolean isMarkedNullable() {
584 return true;
585 }
586 }
587
588 private static class NotNullType extends AbstractTypeWithKnownNullability {
589
590 private NotNullType(@NotNull KotlinType delegate) {
591 super(delegate);
592 }
593
594 @Override
595 public boolean isMarkedNullable() {
596 return false;
597 }
598 }
599
600 }