001 /*
002 * Copyright 2010-2016 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.ClassifierDescriptor;
026 import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
027 import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
028 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
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 SimpleType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
037 public static final SimpleType CANT_INFER_FUNCTION_PARAM_TYPE = ErrorUtils.createErrorType("Cannot be inferred");
038
039 public static class SpecialType extends DelegatingSimpleType {
040 private final String name;
041
042 public SpecialType(String name) {
043 this.name = name;
044 }
045
046 @NotNull
047 @Override
048 protected SimpleType getDelegate() {
049 throw new IllegalStateException(name);
050 }
051
052 @Override
053 public boolean isError() {
054 return false;
055 }
056
057 @NotNull
058 @Override
059 public SimpleType replaceAnnotations(@NotNull Annotations newAnnotations) {
060 throw new IllegalStateException(name);
061 }
062
063 @NotNull
064 @Override
065 public SimpleType makeNullableAsSpecified(boolean newNullability) {
066 throw new IllegalStateException(name);
067 }
068
069 @Override
070 public String toString() {
071 return name;
072 }
073 }
074
075 @NotNull
076 public static final SimpleType NO_EXPECTED_TYPE = new SpecialType("NO_EXPECTED_TYPE");
077
078 public static final SimpleType UNIT_EXPECTED_TYPE = new SpecialType("UNIT_EXPECTED_TYPE");
079
080 public static boolean noExpectedType(@NotNull KotlinType type) {
081 return type == NO_EXPECTED_TYPE || type == UNIT_EXPECTED_TYPE;
082 }
083
084 public static boolean isDontCarePlaceholder(@Nullable KotlinType type) {
085 return type != null && type.getConstructor() == DONT_CARE.getConstructor();
086 }
087
088 @NotNull
089 public static KotlinType makeNullable(@NotNull KotlinType type) {
090 return makeNullableAsSpecified(type, true);
091 }
092
093 @NotNull
094 public static KotlinType makeNotNullable(@NotNull KotlinType type) {
095 return makeNullableAsSpecified(type, false);
096 }
097
098 @NotNull
099 public static KotlinType makeNullableAsSpecified(@NotNull KotlinType type, boolean nullable) {
100 return type.unwrap().makeNullableAsSpecified(nullable);
101 }
102
103 @NotNull
104 public static SimpleType makeNullableIfNeeded(@NotNull SimpleType type, boolean nullable) {
105 if (nullable) {
106 return type.makeNullableAsSpecified(true);
107 }
108 return type;
109 }
110
111 @NotNull
112 public static KotlinType makeNullableIfNeeded(@NotNull KotlinType type, boolean nullable) {
113 if (nullable) {
114 return makeNullable(type);
115 }
116 return type;
117 }
118
119 public static boolean canHaveSubtypes(KotlinTypeChecker typeChecker, @NotNull KotlinType type) {
120 if (type.isMarkedNullable()) {
121 return true;
122 }
123 if (!type.getConstructor().isFinal()) {
124 return true;
125 }
126
127 List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
128 List<TypeProjection> arguments = type.getArguments();
129 for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
130 TypeParameterDescriptor parameterDescriptor = parameters.get(i);
131 TypeProjection typeProjection = arguments.get(i);
132 if (typeProjection.isStarProjection()) return true;
133
134 Variance projectionKind = typeProjection.getProjectionKind();
135 KotlinType argument = typeProjection.getType();
136
137 switch (parameterDescriptor.getVariance()) {
138 case INVARIANT:
139 switch (projectionKind) {
140 case INVARIANT:
141 if (lowerThanBound(typeChecker, argument, parameterDescriptor) || canHaveSubtypes(typeChecker, argument)) {
142 return true;
143 }
144 break;
145 case IN_VARIANCE:
146 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
147 return true;
148 }
149 break;
150 case OUT_VARIANCE:
151 if (canHaveSubtypes(typeChecker, argument)) {
152 return true;
153 }
154 break;
155 }
156 break;
157 case IN_VARIANCE:
158 if (projectionKind != Variance.OUT_VARIANCE) {
159 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
160 return true;
161 }
162 }
163 else {
164 if (canHaveSubtypes(typeChecker, argument)) {
165 return true;
166 }
167 }
168 break;
169 case OUT_VARIANCE:
170 if (projectionKind != Variance.IN_VARIANCE) {
171 if (canHaveSubtypes(typeChecker, argument)) {
172 return true;
173 }
174 }
175 else {
176 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
177 return true;
178 }
179 }
180 break;
181 }
182 }
183 return false;
184 }
185
186 private static boolean lowerThanBound(KotlinTypeChecker typeChecker, KotlinType argument, TypeParameterDescriptor parameterDescriptor) {
187 for (KotlinType bound : parameterDescriptor.getUpperBounds()) {
188 if (typeChecker.isSubtypeOf(argument, bound)) {
189 if (!argument.getConstructor().equals(bound.getConstructor())) {
190 return true;
191 }
192 }
193 }
194 return false;
195 }
196
197 @NotNull
198 public static SimpleType makeUnsubstitutedType(ClassifierDescriptor classifierDescriptor, MemberScope unsubstitutedMemberScope) {
199 if (ErrorUtils.isError(classifierDescriptor)) {
200 return ErrorUtils.createErrorType("Unsubstituted type for " + classifierDescriptor);
201 }
202 TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
203 List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
204 return KotlinTypeFactory.simpleType(
205 Annotations.Companion.getEMPTY(),
206 typeConstructor,
207 arguments,
208 false,
209 unsubstitutedMemberScope
210 );
211 }
212
213 @NotNull
214 public static List<TypeProjection> getDefaultTypeProjections(@NotNull List<TypeParameterDescriptor> parameters) {
215 List<TypeProjection> result = new ArrayList<TypeProjection>(parameters.size());
216 for (TypeParameterDescriptor parameterDescriptor : parameters) {
217 result.add(new TypeProjectionImpl(parameterDescriptor.getDefaultType()));
218 }
219 return org.jetbrains.kotlin.utils.CollectionsKt.toReadOnlyList(result);
220 }
221
222 @NotNull
223 public static List<KotlinType> getImmediateSupertypes(@NotNull KotlinType type) {
224 TypeSubstitutor substitutor = TypeSubstitutor.create(type);
225 Collection<KotlinType> originalSupertypes = type.getConstructor().getSupertypes();
226 List<KotlinType> result = new ArrayList<KotlinType>(originalSupertypes.size());
227 for (KotlinType supertype : originalSupertypes) {
228 KotlinType substitutedType = createSubstitutedSupertype(type, supertype, substitutor);
229 if (substitutedType != null) {
230 result.add(substitutedType);
231 }
232 }
233 return result;
234 }
235
236 @Nullable
237 public static KotlinType createSubstitutedSupertype(
238 @NotNull KotlinType subType,
239 @NotNull KotlinType superType,
240 @NotNull TypeSubstitutor substitutor
241 ) {
242 KotlinType substitutedType = substitutor.substitute(superType, Variance.INVARIANT);
243 if (substitutedType != null) {
244 return makeNullableIfNeeded(substitutedType, subType.isMarkedNullable());
245 }
246 return null;
247 }
248
249 private static void collectAllSupertypes(@NotNull KotlinType type, @NotNull Set<KotlinType> result) {
250 List<KotlinType> immediateSupertypes = getImmediateSupertypes(type);
251 result.addAll(immediateSupertypes);
252 for (KotlinType supertype : immediateSupertypes) {
253 collectAllSupertypes(supertype, result);
254 }
255 }
256
257
258 @NotNull
259 public static Set<KotlinType> getAllSupertypes(@NotNull KotlinType type) {
260 // 15 is obtained by experimentation: JDK classes like ArrayList tend to have so many supertypes,
261 // the average number is lower
262 Set<KotlinType> result = new LinkedHashSet<KotlinType>(15);
263 collectAllSupertypes(type, result);
264 return result;
265 }
266
267 /**
268 * A work-around of the generic nullability problem in the type checker
269 * Semantics should be the same as `!isSubtype(T, Any)`
270 * @return true if a value of this type can be null
271 */
272 public static boolean isNullableType(@NotNull KotlinType type) {
273 if (type.isMarkedNullable()) {
274 return true;
275 }
276 if (FlexibleTypesKt.isFlexible(type) && isNullableType(FlexibleTypesKt.asFlexibleType(type).getUpperBound())) {
277 return true;
278 }
279 if (isTypeParameter(type)) {
280 return hasNullableSuperType(type);
281 }
282 return false;
283 }
284
285 /**
286 * Differs from `isNullableType` only by treating type parameters: acceptsNullable(T) <=> T has nullable lower bound
287 * Semantics should be the same as `isSubtype(Nothing?, T)`
288 * @return true if `null` can be assigned to storage of this type
289 */
290 public static boolean acceptsNullable(@NotNull KotlinType type) {
291 if (type.isMarkedNullable()) {
292 return true;
293 }
294 if (FlexibleTypesKt.isFlexible(type) && acceptsNullable(FlexibleTypesKt.asFlexibleType(type).getUpperBound())) {
295 return true;
296 }
297 return false;
298 }
299
300 public static boolean hasNullableSuperType(@NotNull KotlinType type) {
301 if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
302 // A class/trait cannot have a nullable supertype
303 return false;
304 }
305
306 for (KotlinType supertype : getImmediateSupertypes(type)) {
307 if (isNullableType(supertype)) return true;
308 }
309
310 return false;
311 }
312
313 @Nullable
314 public static ClassDescriptor getClassDescriptor(@NotNull KotlinType type) {
315 DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
316 if (declarationDescriptor instanceof ClassDescriptor) {
317 return (ClassDescriptor) declarationDescriptor;
318 }
319 return null;
320 }
321
322 @NotNull
323 public static KotlinType substituteParameters(@NotNull ClassDescriptor clazz, @NotNull List<KotlinType> typeArguments) {
324 List<TypeProjection> projections = CollectionsKt.map(typeArguments, new Function1<KotlinType, TypeProjection>() {
325 @Override
326 public TypeProjection invoke(KotlinType type) {
327 return new TypeProjectionImpl(type);
328 }
329 });
330
331 return substituteProjectionsForParameters(clazz, projections);
332 }
333
334 @NotNull
335 public static KotlinType substituteProjectionsForParameters(@NotNull ClassDescriptor clazz, @NotNull List<TypeProjection> projections) {
336 List<TypeParameterDescriptor> clazzTypeParameters = clazz.getTypeConstructor().getParameters();
337 if (clazzTypeParameters.size() != projections.size()) {
338 throw new IllegalArgumentException("type parameter counts do not match: " + clazz + ", " + projections);
339 }
340
341 Map<TypeConstructor, TypeProjection> substitutions = org.jetbrains.kotlin.utils.CollectionsKt
342 .newHashMapWithExpectedSize(clazzTypeParameters.size());
343
344 for (int i = 0; i < clazzTypeParameters.size(); ++i) {
345 TypeConstructor typeConstructor = clazzTypeParameters.get(i).getTypeConstructor();
346 substitutions.put(typeConstructor, projections.get(i));
347 }
348
349 return TypeSubstitutor.create(substitutions).substitute(clazz.getDefaultType(), Variance.INVARIANT);
350 }
351
352 public static boolean equalTypes(@NotNull KotlinType a, @NotNull KotlinType b) {
353 return KotlinTypeChecker.DEFAULT.isSubtypeOf(a, b) && KotlinTypeChecker.DEFAULT.isSubtypeOf(b, a);
354 }
355
356 public static boolean dependsOnTypeParameters(@NotNull KotlinType type, @NotNull Collection<TypeParameterDescriptor> typeParameters) {
357 return dependsOnTypeConstructors(type, CollectionsKt.map(
358 typeParameters,
359 new Function1<TypeParameterDescriptor, TypeConstructor>() {
360 @Override
361 public TypeConstructor invoke(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
362 return typeParameterDescriptor.getTypeConstructor();
363 }
364 }
365 ));
366 }
367
368 public static boolean dependsOnTypeConstructors(@NotNull KotlinType type, @NotNull Collection<TypeConstructor> typeParameterConstructors) {
369 if (typeParameterConstructors.contains(type.getConstructor())) return true;
370 for (TypeProjection typeProjection : type.getArguments()) {
371 if (!typeProjection.isStarProjection() && dependsOnTypeConstructors(typeProjection.getType(), typeParameterConstructors)) {
372 return true;
373 }
374 }
375 return false;
376 }
377
378 public static boolean contains(@Nullable KotlinType type, @NotNull final KotlinType specialType) {
379 return contains(type, new Function1<UnwrappedType, Boolean>() {
380 @Override
381 public Boolean invoke(UnwrappedType type) {
382 return specialType.equals(type);
383 }
384 });
385 }
386
387 public static boolean contains(
388 @Nullable KotlinType type,
389 @NotNull Function1<UnwrappedType, Boolean> isSpecialType
390 ) {
391 if (type == null) return false;
392
393 UnwrappedType unwrappedType = type.unwrap();
394 if (isSpecialType.invoke(unwrappedType)) return true;
395
396 FlexibleType flexibleType = unwrappedType instanceof FlexibleType ? (FlexibleType) unwrappedType : null;
397 if (flexibleType != null
398 && (contains(flexibleType.getLowerBound(), isSpecialType) || contains(flexibleType.getUpperBound(), isSpecialType))) {
399 return true;
400 }
401 for (TypeProjection projection : type.getArguments()) {
402 if (!projection.isStarProjection() && contains(projection.getType(), isSpecialType)) return true;
403 }
404 return false;
405 }
406
407 @NotNull
408 public static TypeProjection makeStarProjection(@NotNull TypeParameterDescriptor parameterDescriptor) {
409 return new StarProjectionImpl(parameterDescriptor);
410 }
411
412 @NotNull
413 public static KotlinType getDefaultPrimitiveNumberType(@NotNull IntegerValueTypeConstructor numberValueTypeConstructor) {
414 KotlinType type = getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
415 assert type != null : "Strange number value type constructor: " + numberValueTypeConstructor + ". " +
416 "Super types doesn't contain double, int or long: " + numberValueTypeConstructor.getSupertypes();
417 return type;
418 }
419
420 @Nullable
421 public static KotlinType getDefaultPrimitiveNumberType(@NotNull Collection<KotlinType> supertypes) {
422 if (supertypes.isEmpty()) {
423 return null;
424 }
425
426 KotlinBuiltIns builtIns = supertypes.iterator().next().getConstructor().getBuiltIns();
427 KotlinType doubleType = builtIns.getDoubleType();
428 if (supertypes.contains(doubleType)) {
429 return doubleType;
430 }
431 KotlinType intType = builtIns.getIntType();
432 if (supertypes.contains(intType)) {
433 return intType;
434 }
435 KotlinType longType = builtIns.getLongType();
436 if (supertypes.contains(longType)) {
437 return longType;
438 }
439 return null;
440 }
441
442 @NotNull
443 public static KotlinType getPrimitiveNumberType(
444 @NotNull IntegerValueTypeConstructor numberValueTypeConstructor,
445 @NotNull KotlinType expectedType
446 ) {
447 if (noExpectedType(expectedType) || expectedType.isError()) {
448 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
449 }
450 for (KotlinType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) {
451 if (KotlinTypeChecker.DEFAULT.isSubtypeOf(primitiveNumberType, expectedType)) {
452 return primitiveNumberType;
453 }
454 }
455 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
456 }
457
458 public static boolean isTypeParameter(@NotNull KotlinType type) {
459 return getTypeParameterDescriptorOrNull(type) != null;
460 }
461
462 public static boolean isReifiedTypeParameter(@NotNull KotlinType type) {
463 TypeParameterDescriptor typeParameterDescriptor = getTypeParameterDescriptorOrNull(type);
464 return typeParameterDescriptor != null && typeParameterDescriptor.isReified();
465 }
466
467 public static boolean isNonReifiedTypeParameter(@NotNull KotlinType type) {
468 TypeParameterDescriptor typeParameterDescriptor = getTypeParameterDescriptorOrNull(type);
469 return typeParameterDescriptor != null && !typeParameterDescriptor.isReified();
470 }
471
472 @Nullable
473 public static TypeParameterDescriptor getTypeParameterDescriptorOrNull(@NotNull KotlinType type) {
474 if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
475 return (TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor();
476 }
477 return null;
478 }
479 }