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