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 kotlin.Function1;
027 import kotlin.KotlinPackage;
028 import org.jetbrains.annotations.NotNull;
029 import org.jetbrains.annotations.Nullable;
030 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
031 import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
032 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
033 import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
034 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
035 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
036 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
037 import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstructor;
038 import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
039 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
040 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
041 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
042 import org.jetbrains.jet.utils.DFS;
043
044 import java.util.*;
045
046 public class TypeUtils {
047 public static final JetType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
048 public static final JetType PLACEHOLDER_FUNCTION_TYPE = ErrorUtils.createErrorTypeWithCustomDebugName("PLACEHOLDER_FUNCTION_TYPE");
049
050 public static final JetType CANT_INFER_LAMBDA_PARAM_TYPE = ErrorUtils.createErrorType("Cannot be inferred");
051
052 public static class SpecialType implements JetType {
053 private final String name;
054
055 public SpecialType(String name) {
056 this.name = name;
057 }
058
059 @NotNull
060 @Override
061 public TypeConstructor getConstructor() {
062 throw new IllegalStateException(name);
063 }
064
065 @NotNull
066 @Override
067 public List<TypeProjection> getArguments() {
068 throw new IllegalStateException(name);
069 }
070
071 @Override
072 public boolean isNullable() {
073 throw new IllegalStateException(name);
074 }
075
076 @NotNull
077 @Override
078 public JetScope getMemberScope() {
079 throw new IllegalStateException(name);
080 }
081
082 @Override
083 public boolean isError() {
084 return false;
085 }
086
087 @NotNull
088 @Override
089 public Annotations getAnnotations() {
090 throw new IllegalStateException(name);
091 }
092
093 @Override
094 public String toString() {
095 return name;
096 }
097 }
098
099 public static final JetType NO_EXPECTED_TYPE = new SpecialType("NO_EXPECTED_TYPE");
100
101 public static final JetType UNIT_EXPECTED_TYPE = new SpecialType("UNIT_EXPECTED_TYPE");
102
103 public static boolean noExpectedType(@NotNull JetType type) {
104 return type == NO_EXPECTED_TYPE || type == UNIT_EXPECTED_TYPE;
105 }
106
107 @NotNull
108 public static JetType makeNullable(@NotNull JetType type) {
109 return makeNullableAsSpecified(type, true);
110 }
111
112 @NotNull
113 public static JetType makeNotNullable(@NotNull JetType type) {
114 return makeNullableAsSpecified(type, false);
115 }
116
117 @NotNull
118 public static JetType makeNullableAsSpecified(@NotNull JetType type, boolean nullable) {
119 // Wrapping serves two purposes here
120 // 1. It's requires less memory than copying with a changed nullability flag: a copy has many fields, while a wrapper has only one
121 // 2. It preserves laziness of types
122
123 // Unwrap to avoid long delegation call chains
124 if (type instanceof AbstractTypeWithKnownNullability) {
125 return makeNullableAsSpecified(((AbstractTypeWithKnownNullability) type).delegate, nullable);
126 }
127
128 // checking to preserve laziness
129 if (!(type instanceof LazyType) && type.isNullable() == nullable) {
130 return type;
131 }
132
133 return nullable ? new NullableType(type) : new NotNullType(type);
134 }
135
136 @NotNull
137 public static JetType makeNullableIfNeeded(@NotNull JetType type, boolean nullable) {
138 if (nullable) {
139 return makeNullable(type);
140 }
141 return type;
142 }
143
144 public static boolean isIntersectionEmpty(@NotNull JetType typeA, @NotNull JetType typeB) {
145 return intersect(JetTypeChecker.INSTANCE, Sets.newLinkedHashSet(Lists.newArrayList(typeA, typeB))) == null;
146 }
147
148 @Nullable
149 public static JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set<JetType> types) {
150 if (types.isEmpty()) {
151 return KotlinBuiltIns.getInstance().getNullableAnyType();
152 }
153
154 if (types.size() == 1) {
155 return types.iterator().next();
156 }
157
158 // Intersection of T1..Tn is an intersection of their non-null versions,
159 // made nullable is they all were nullable
160 boolean allNullable = true;
161 boolean nothingTypePresent = false;
162 List<JetType> nullabilityStripped = Lists.newArrayList();
163 for (JetType type : types) {
164 nothingTypePresent |= KotlinBuiltIns.getInstance().isNothingOrNullableNothing(type);
165 allNullable &= type.isNullable();
166 nullabilityStripped.add(makeNotNullable(type));
167 }
168
169 if (nothingTypePresent) {
170 return allNullable ? KotlinBuiltIns.getInstance().getNullableNothingType() : KotlinBuiltIns.getInstance().getNothingType();
171 }
172
173 // Now we remove types that have subtypes in the list
174 List<JetType> resultingTypes = Lists.newArrayList();
175 outer:
176 for (JetType type : nullabilityStripped) {
177 if (!canHaveSubtypes(typeChecker, type)) {
178 for (JetType other : nullabilityStripped) {
179 // It makes sense to check for subtyping (other <: type), despite that
180 // type is not supposed to be open, for there're enums
181 if (!TypeUnifier.mayBeEqual(type, other) && !typeChecker.isSubtypeOf(type, other) && !typeChecker.isSubtypeOf(other, type)) {
182 return null;
183 }
184 }
185 return makeNullableAsSpecified(type, allNullable);
186 }
187 else {
188 for (JetType other : nullabilityStripped) {
189 if (!type.equals(other) && typeChecker.isSubtypeOf(other, type)) {
190 continue outer;
191 }
192
193 }
194 }
195
196 // Don't add type if it is already present, to avoid trivial type intersections in result
197 for (JetType other : resultingTypes) {
198 if (typeChecker.equalTypes(other, type)) {
199 continue outer;
200 }
201 }
202 resultingTypes.add(type);
203 }
204
205 if (resultingTypes.size() == 1) {
206 return makeNullableAsSpecified(resultingTypes.get(0), allNullable);
207 }
208
209
210 TypeConstructor constructor = new IntersectionTypeConstructor(Annotations.EMPTY, resultingTypes);
211
212 JetScope[] scopes = new JetScope[resultingTypes.size()];
213 int i = 0;
214 for (JetType type : resultingTypes) {
215 scopes[i] = type.getMemberScope();
216 i++;
217 }
218
219 return new JetTypeImpl(
220 Annotations.EMPTY,
221 constructor,
222 allNullable,
223 Collections.<TypeProjection>emptyList(),
224 new ChainedScope(null, "member scope for intersection type " + constructor, scopes)); // TODO : check intersectibility, don't use a chanied scope
225 }
226
227 private static class TypeUnifier {
228 private static class TypeParameterUsage {
229 private final TypeParameterDescriptor typeParameterDescriptor;
230 private final Variance howTheTypeParameterIsUsed;
231
232 public TypeParameterUsage(TypeParameterDescriptor typeParameterDescriptor, Variance howTheTypeParameterIsUsed) {
233 this.typeParameterDescriptor = typeParameterDescriptor;
234 this.howTheTypeParameterIsUsed = howTheTypeParameterIsUsed;
235 }
236 }
237
238 public static boolean mayBeEqual(@NotNull JetType type, @NotNull JetType other) {
239 return unify(type, other);
240 }
241
242 private static boolean unify(JetType withParameters, JetType expected) {
243 // T -> how T is used
244 final Map<TypeParameterDescriptor, Variance> parameters = Maps.newHashMap();
245 Processor<TypeParameterUsage> processor = new Processor<TypeParameterUsage>() {
246 @Override
247 public boolean process(TypeParameterUsage parameterUsage) {
248 Variance howTheTypeIsUsedBefore = parameters.get(parameterUsage.typeParameterDescriptor);
249 if (howTheTypeIsUsedBefore == null) {
250 howTheTypeIsUsedBefore = Variance.INVARIANT;
251 }
252 parameters.put(parameterUsage.typeParameterDescriptor,
253 parameterUsage.howTheTypeParameterIsUsed.superpose(howTheTypeIsUsedBefore));
254 return true;
255 }
256 };
257 processAllTypeParameters(withParameters, Variance.INVARIANT, processor);
258 processAllTypeParameters(expected, Variance.INVARIANT, processor);
259 ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
260 constraintSystem.registerTypeVariables(parameters);
261 constraintSystem.addSubtypeConstraint(withParameters, expected, ConstraintPosition.SPECIAL);
262
263 return constraintSystem.getStatus().isSuccessful();
264 }
265
266 private static void processAllTypeParameters(JetType type, Variance howThiTypeIsUsed, Processor<TypeParameterUsage> result) {
267 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
268 if (descriptor instanceof TypeParameterDescriptor) {
269 result.process(new TypeParameterUsage((TypeParameterDescriptor)descriptor, howThiTypeIsUsed));
270 }
271 for (TypeProjection projection : type.getArguments()) {
272 processAllTypeParameters(projection.getType(), projection.getProjectionKind(), result);
273 }
274 }
275 }
276
277 public static boolean canHaveSubtypes(JetTypeChecker typeChecker, JetType type) {
278 if (type.isNullable()) {
279 return true;
280 }
281 if (!type.getConstructor().isFinal()) {
282 return true;
283 }
284
285 List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
286 List<TypeProjection> arguments = type.getArguments();
287 for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
288 TypeParameterDescriptor parameterDescriptor = parameters.get(i);
289 TypeProjection typeProjection = arguments.get(i);
290 Variance projectionKind = typeProjection.getProjectionKind();
291 JetType argument = typeProjection.getType();
292
293 switch (parameterDescriptor.getVariance()) {
294 case INVARIANT:
295 switch (projectionKind) {
296 case INVARIANT:
297 if (lowerThanBound(typeChecker, argument, parameterDescriptor) || canHaveSubtypes(typeChecker, argument)) {
298 return true;
299 }
300 break;
301 case IN_VARIANCE:
302 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
303 return true;
304 }
305 break;
306 case OUT_VARIANCE:
307 if (canHaveSubtypes(typeChecker, argument)) {
308 return true;
309 }
310 break;
311 }
312 break;
313 case IN_VARIANCE:
314 if (projectionKind != Variance.OUT_VARIANCE) {
315 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
316 return true;
317 }
318 }
319 else {
320 if (canHaveSubtypes(typeChecker, argument)) {
321 return true;
322 }
323 }
324 break;
325 case OUT_VARIANCE:
326 if (projectionKind != Variance.IN_VARIANCE) {
327 if (canHaveSubtypes(typeChecker, argument)) {
328 return true;
329 }
330 }
331 else {
332 if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
333 return true;
334 }
335 }
336 break;
337 }
338 }
339 return false;
340 }
341
342 private static boolean lowerThanBound(JetTypeChecker typeChecker, JetType argument, TypeParameterDescriptor parameterDescriptor) {
343 for (JetType bound : parameterDescriptor.getUpperBounds()) {
344 if (typeChecker.isSubtypeOf(argument, bound)) {
345 if (!argument.getConstructor().equals(bound.getConstructor())) {
346 return true;
347 }
348 }
349 }
350 return false;
351 }
352
353 @NotNull
354 public static JetType makeUnsubstitutedType(ClassDescriptor classDescriptor, JetScope unsubstitutedMemberScope) {
355 if (ErrorUtils.isError(classDescriptor)) {
356 return ErrorUtils.createErrorType("Unsubstituted type for " + classDescriptor);
357 }
358 TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
359 List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
360 return new JetTypeImpl(
361 Annotations.EMPTY,
362 typeConstructor,
363 false,
364 arguments,
365 unsubstitutedMemberScope
366 );
367 }
368
369 @NotNull
370 public static List<TypeProjection> getDefaultTypeProjections(List<TypeParameterDescriptor> parameters) {
371 List<TypeProjection> result = new ArrayList<TypeProjection>();
372 for (TypeParameterDescriptor parameterDescriptor : parameters) {
373 result.add(new TypeProjectionImpl(parameterDescriptor.getDefaultType()));
374 }
375 return result;
376 }
377
378 private static void collectImmediateSupertypes(@NotNull JetType type, @NotNull Collection<JetType> result) {
379 TypeSubstitutor substitutor = TypeSubstitutor.create(type);
380 for (JetType supertype : type.getConstructor().getSupertypes()) {
381 result.add(substitutor.substitute(supertype, Variance.INVARIANT));
382 }
383 }
384
385 @NotNull
386 public static List<JetType> getImmediateSupertypes(@NotNull JetType type) {
387 List<JetType> result = Lists.newArrayList();
388 collectImmediateSupertypes(type, result);
389 return result;
390 }
391
392 private static void collectAllSupertypes(@NotNull JetType type, @NotNull Set<JetType> result) {
393 List<JetType> immediateSupertypes = getImmediateSupertypes(type);
394 result.addAll(immediateSupertypes);
395 for (JetType supertype : immediateSupertypes) {
396 collectAllSupertypes(supertype, result);
397 }
398 }
399
400
401 @NotNull
402 public static Set<JetType> getAllSupertypes(@NotNull JetType type) {
403 // 15 is obtained by experimentation: JDK classes like ArrayList tend to have so many supertypes,
404 // the average number is lower
405 Set<JetType> result = new LinkedHashSet<JetType>(15);
406 collectAllSupertypes(type, result);
407 return result;
408 }
409
410 public static boolean hasNullableLowerBound(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
411 for (JetType bound : typeParameterDescriptor.getLowerBounds()) {
412 if (bound.isNullable()) {
413 return true;
414 }
415 }
416 return false;
417 }
418
419 public static boolean hasNullableSuperType(@NotNull JetType type) {
420 if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
421 // A class/trait cannot have a nullable supertype
422 return false;
423 }
424
425 for (JetType supertype : getImmediateSupertypes(type)) {
426 if (supertype.isNullable()) return true;
427 if (hasNullableSuperType(supertype)) return true;
428 }
429
430 return false;
431 }
432
433 @Nullable
434 public static ClassDescriptor getClassDescriptor(@NotNull JetType type) {
435 DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
436 if (declarationDescriptor instanceof ClassDescriptor) {
437 return (ClassDescriptor) declarationDescriptor;
438 }
439 return null;
440 }
441
442 @NotNull
443 public static JetType substituteParameters(@NotNull ClassDescriptor clazz, @NotNull List<JetType> typeArguments) {
444 List<TypeProjection> projections = KotlinPackage.map(typeArguments, new Function1<JetType, TypeProjection>() {
445 @Override
446 public TypeProjection invoke(JetType type) {
447 return new TypeProjectionImpl(type);
448 }
449 });
450
451 return substituteProjectionsForParameters(clazz, projections);
452 }
453
454 @NotNull
455 public static JetType substituteProjectionsForParameters(@NotNull ClassDescriptor clazz, @NotNull List<TypeProjection> projections) {
456 List<TypeParameterDescriptor> clazzTypeParameters = clazz.getTypeConstructor().getParameters();
457 if (clazzTypeParameters.size() != projections.size()) {
458 throw new IllegalArgumentException("type parameter counts do not match: " + clazz + ", " + projections);
459 }
460
461 Map<TypeConstructor, TypeProjection> substitutions = Maps.newHashMap();
462
463 for (int i = 0; i < clazzTypeParameters.size(); ++i) {
464 TypeConstructor typeConstructor = clazzTypeParameters.get(i).getTypeConstructor();
465 substitutions.put(typeConstructor, projections.get(i));
466 }
467
468 return TypeSubstitutor.create(substitutions).substitute(clazz.getDefaultType(), Variance.INVARIANT);
469 }
470
471 public static boolean equalTypes(@NotNull JetType a, @NotNull JetType b) {
472 return JetTypeChecker.INSTANCE.isSubtypeOf(a, b) && JetTypeChecker.INSTANCE.isSubtypeOf(b, a);
473 }
474
475 public static boolean dependsOnTypeParameters(@NotNull JetType type, @NotNull Collection<TypeParameterDescriptor> typeParameters) {
476 return dependsOnTypeConstructors(type, Collections2
477 .transform(typeParameters, new Function<TypeParameterDescriptor, TypeConstructor>() {
478 @Override
479 public TypeConstructor apply(@Nullable TypeParameterDescriptor typeParameterDescriptor) {
480 assert typeParameterDescriptor != null;
481 return typeParameterDescriptor.getTypeConstructor();
482 }
483 }));
484 }
485
486 public static boolean dependsOnTypeConstructors(@NotNull JetType type, @NotNull Collection<TypeConstructor> typeParameterConstructors) {
487 if (typeParameterConstructors.contains(type.getConstructor())) return true;
488 for (TypeProjection typeProjection : type.getArguments()) {
489 if (dependsOnTypeConstructors(typeProjection.getType(), typeParameterConstructors)) {
490 return true;
491 }
492 }
493 return false;
494 }
495
496 public static boolean containsSpecialType(@Nullable JetType type, @NotNull final JetType specialType) {
497 return containsSpecialType(type, new Function1<JetType, Boolean>() {
498 @Override
499 public Boolean invoke(JetType type) {
500 return specialType.equals(type);
501 }
502 });
503 }
504
505 public static boolean containsSpecialType(
506 @Nullable JetType type,
507 @NotNull Function1<JetType, Boolean> isSpecialType
508 ) {
509 if (type == null) return false;
510 if (isSpecialType.invoke(type)) return true;
511 if (type instanceof PackageType) return false;
512 for (TypeProjection projection : type.getArguments()) {
513 if (containsSpecialType(projection.getType(), isSpecialType)) return true;
514 }
515 return false;
516 }
517
518 @NotNull
519 public static TypeProjection makeStarProjection(@NotNull TypeParameterDescriptor parameterDescriptor) {
520 return new TypeProjectionImpl(parameterDescriptor.getVariance() == Variance.OUT_VARIANCE
521 ? Variance.INVARIANT
522 : Variance.OUT_VARIANCE, parameterDescriptor.getUpperBoundsAsType());
523 }
524
525 @Nullable
526 public static JetType commonSupertypeForNumberTypes(@NotNull Collection<JetType> numberLowerBounds) {
527 if (numberLowerBounds.isEmpty()) return null;
528 Set<JetType> intersectionOfSupertypes = getIntersectionOfSupertypes(numberLowerBounds);
529 JetType primitiveNumberType = getDefaultPrimitiveNumberType(intersectionOfSupertypes);
530 if (primitiveNumberType != null) {
531 return primitiveNumberType;
532 }
533 return CommonSupertypes.commonSupertype(numberLowerBounds);
534 }
535
536 @NotNull
537 private static Set<JetType> getIntersectionOfSupertypes(@NotNull Collection<JetType> types) {
538 Set<JetType> upperBounds = Sets.newHashSet();
539 for (JetType type : types) {
540 Set<JetType> supertypes = Sets.newHashSet(type.getConstructor().getSupertypes());
541 if (upperBounds.isEmpty()) {
542 upperBounds.addAll(supertypes);
543 }
544 else {
545 upperBounds = Sets.intersection(upperBounds, supertypes);
546 }
547 }
548 return upperBounds;
549 }
550
551 @NotNull
552 public static JetType getDefaultPrimitiveNumberType(@NotNull IntegerValueTypeConstructor numberValueTypeConstructor) {
553 JetType type = getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
554 assert type != null : "Strange number value type constructor: " + numberValueTypeConstructor + ". " +
555 "Super types doesn't contain double, int or long: " + numberValueTypeConstructor.getSupertypes();
556 return type;
557 }
558
559 @Nullable
560 private static JetType getDefaultPrimitiveNumberType(@NotNull Collection<JetType> supertypes) {
561 JetType doubleType = KotlinBuiltIns.getInstance().getDoubleType();
562 if (supertypes.contains(doubleType)) {
563 return doubleType;
564 }
565 JetType intType = KotlinBuiltIns.getInstance().getIntType();
566 if (supertypes.contains(intType)) {
567 return intType;
568 }
569 JetType longType = KotlinBuiltIns.getInstance().getLongType();
570 if (supertypes.contains(longType)) {
571 return longType;
572 }
573 return null;
574 }
575
576 @NotNull
577 public static JetType getPrimitiveNumberType(
578 @NotNull IntegerValueTypeConstructor numberValueTypeConstructor,
579 @NotNull JetType expectedType
580 ) {
581 if (noExpectedType(expectedType) || expectedType.isError()) {
582 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
583 }
584 for (JetType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) {
585 if (JetTypeChecker.INSTANCE.isSubtypeOf(primitiveNumberType, expectedType)) {
586 return primitiveNumberType;
587 }
588 }
589 return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
590 }
591
592 @NotNull
593 public static Pair<Collection<JetType>, Collection<JetType>> filterNumberTypes(@NotNull Collection<JetType> types) {
594 Collection<JetType> numberTypes = Sets.newLinkedHashSet();
595 Collection<JetType> otherTypes = Sets.newLinkedHashSet();
596 for (JetType type : types) {
597 if (type.getConstructor() instanceof IntegerValueTypeConstructor) {
598 numberTypes.add(type);
599 }
600 else {
601 otherTypes.add(type);
602 }
603 }
604 return Pair.create(otherTypes, numberTypes);
605 }
606
607 public static List<TypeConstructor> topologicallySortSuperclassesAndRecordAllInstances(
608 @NotNull JetType type,
609 @NotNull final Map<TypeConstructor, Set<JetType>> constructorToAllInstances,
610 @NotNull final Set<TypeConstructor> visited
611 ) {
612 return DFS.dfs(
613 Collections.singletonList(type),
614 new DFS.Neighbors<JetType>() {
615 @NotNull
616 @Override
617 public Iterable<JetType> getNeighbors(JetType current) {
618 TypeSubstitutor substitutor = TypeSubstitutor.create(current);
619 List<JetType> result = Lists.newArrayList();
620 for (JetType supertype : current.getConstructor().getSupertypes()) {
621 if (visited.contains(supertype.getConstructor())) {
622 continue;
623 }
624 result.add(substitutor.safeSubstitute(supertype, Variance.INVARIANT));
625 }
626 return result;
627 }
628 },
629 new DFS.Visited<JetType>() {
630 @Override
631 public boolean checkAndMarkVisited(JetType current) {
632 return visited.add(current.getConstructor());
633 }
634 },
635 new DFS.NodeHandlerWithListResult<JetType, TypeConstructor>() {
636 @Override
637 public void beforeChildren(JetType current) {
638 TypeConstructor constructor = current.getConstructor();
639
640 Set<JetType> instances = constructorToAllInstances.get(constructor);
641 if (instances == null) {
642 instances = new HashSet<JetType>();
643 constructorToAllInstances.put(constructor, instances);
644 }
645 instances.add(current);
646 }
647
648 @Override
649 public void afterChildren(JetType current) {
650 result.addFirst(current.getConstructor());
651 }
652 }
653 );
654 }
655
656 public static TypeSubstitutor makeConstantSubstitutor(Collection<TypeParameterDescriptor> typeParameterDescriptors, JetType type) {
657 final Set<TypeConstructor> constructors = Sets.newHashSet();
658 for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) {
659 constructors.add(typeParameterDescriptor.getTypeConstructor());
660 }
661 final TypeProjection projection = new TypeProjectionImpl(type);
662
663 return TypeSubstitutor.create(new TypeSubstitution() {
664 @Override
665 public TypeProjection get(TypeConstructor key) {
666 if (constructors.contains(key)) {
667 return projection;
668 }
669 return null;
670 }
671
672 @Override
673 public boolean isEmpty() {
674 return false;
675 }
676 });
677 }
678
679 public static TypeSubstitutor makeSubstitutorForTypeParametersMap(
680 @NotNull final Map<TypeParameterDescriptor, TypeProjection> substitutionContext
681 ) {
682 return TypeSubstitutor.create(new TypeSubstitution() {
683 @Nullable
684 @Override
685 public TypeProjection get(TypeConstructor key) {
686 DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
687 if (declarationDescriptor instanceof TypeParameterDescriptor) {
688 TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
689 return substitutionContext.get(descriptor);
690 }
691 return null;
692 }
693
694 @Override
695 public boolean isEmpty() {
696 return substitutionContext.isEmpty();
697 }
698
699 @Override
700 public String toString() {
701 return substitutionContext.toString();
702 }
703 });
704 }
705
706 private static abstract class AbstractTypeWithKnownNullability extends AbstractJetType {
707 private final JetType delegate;
708
709 private AbstractTypeWithKnownNullability(@NotNull JetType delegate) {
710 this.delegate = delegate;
711 }
712
713 @Override
714 @NotNull
715 public TypeConstructor getConstructor() {
716 return delegate.getConstructor();
717 }
718
719 @Override
720 @NotNull
721 public List<TypeProjection> getArguments() {
722 return delegate.getArguments();
723 }
724
725 @Override
726 public abstract boolean isNullable();
727
728 @Override
729 @NotNull
730 public JetScope getMemberScope() {
731 return delegate.getMemberScope();
732 }
733
734 @Override
735 public boolean isError() {
736 return delegate.isError();
737 }
738
739 @Override
740 @NotNull
741 public Annotations getAnnotations() {
742 return delegate.getAnnotations();
743 }
744 }
745
746 private static class NullableType extends AbstractTypeWithKnownNullability {
747
748 private NullableType(@NotNull JetType delegate) {
749 super(delegate);
750 }
751
752 @Override
753 public boolean isNullable() {
754 return true;
755 }
756 }
757
758 private static class NotNullType extends AbstractTypeWithKnownNullability {
759
760 private NotNullType(@NotNull JetType delegate) {
761 super(delegate);
762 }
763
764 @Override
765 public boolean isNullable() {
766 return false;
767 }
768 }
769
770 }