Make getUpperBoundsAsType an utility, remove from TypeParameterDescriptor
This commit is contained in:
+10
-8
@@ -32,14 +32,13 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.kotlin.types.Variance;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.components.TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT;
|
||||
import static org.jetbrains.kotlin.load.java.components.TypeUsage.UPPER_BOUND;
|
||||
@@ -140,13 +139,16 @@ public class AlternativeMethodSignatureData extends ElementAlternativeSignatureD
|
||||
for (TypeParameterDescriptor parameter : methodTypeParameters) {
|
||||
int index = parameter.getIndex();
|
||||
|
||||
KotlinType substituted = substitutor.substitute(parameter.getUpperBoundsAsType(), Variance.INVARIANT);
|
||||
KotlinType upperBoundsAsType = TypeIntersector.getUpperBoundsAsType(parameter);
|
||||
KotlinType substituted = substitutor.substitute(upperBoundsAsType, Variance.INVARIANT);
|
||||
assert substituted != null;
|
||||
|
||||
if (!TypeUtils.equalTypes(substituted, altTypeParameters.get(index).getUpperBoundsAsType())) {
|
||||
KotlinType altUpperBoundsAsType = TypeIntersector.getUpperBoundsAsType(altTypeParameters.get(index));
|
||||
if (!TypeUtils.equalTypes(substituted, altUpperBoundsAsType)) {
|
||||
throw new AlternativeSignatureMismatchException(
|
||||
"Type parameter's upper bound changed for method which overrides another: "
|
||||
+ altTypeParameters.get(index).getUpperBoundsAsType() + ", was: " + parameter.getUpperBoundsAsType());
|
||||
+ altUpperBoundsAsType + ", was: " + upperBoundsAsType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -150,7 +150,7 @@ public class TypeTransformingVisitor extends KtVisitor<KotlinType, Void> {
|
||||
|
||||
KtScope memberScope;
|
||||
if (typeConstructorClassifier instanceof TypeParameterDescriptor) {
|
||||
memberScope = ((TypeParameterDescriptor) typeConstructorClassifier).getUpperBoundsAsType().getMemberScope();
|
||||
memberScope = typeConstructorClassifier.getDefaultType().getMemberScope();
|
||||
}
|
||||
else if (typeConstructorClassifier instanceof ClassDescriptor) {
|
||||
memberScope = ((ClassDescriptor) typeConstructorClassifier).getMemberScope(altArguments);
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeIntersector
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
@@ -324,7 +325,7 @@ public object Renderers {
|
||||
}
|
||||
|
||||
val explanation: String
|
||||
val upperBound = typeParameterWithCapturedConstraint.getUpperBoundsAsType()
|
||||
val upperBound = TypeIntersector.getUpperBoundsAsType(typeParameterWithCapturedConstraint)
|
||||
if (!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.typeProjection.getProjectionKind() == Variance.IN_VARIANCE) {
|
||||
explanation = "Type parameter has an upper bound '" + result.getTypeRenderer().render(upperBound) + "'" +
|
||||
" that cannot be satisfied capturing 'in' projection"
|
||||
|
||||
@@ -62,7 +62,8 @@ import java.util.*;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
import static org.jetbrains.kotlin.lexer.KtTokens.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.CONSTRUCTOR;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.PACKAGE_TO_FILES;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveModalityFromModifiers;
|
||||
import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveVisibilityFromModifiers;
|
||||
@@ -539,7 +540,7 @@ public class DescriptorResolver {
|
||||
@NotNull TypeParameterDescriptor parameter,
|
||||
@NotNull KtTypeParameter typeParameter
|
||||
) {
|
||||
if (KotlinBuiltIns.isNothing(parameter.getUpperBoundsAsType())) {
|
||||
if (KotlinBuiltIns.isNothing(TypeIntersector.getUpperBoundsAsType(parameter))) {
|
||||
trace.report(CONFLICTING_UPPER_BOUNDS.on(typeParameter, parameter));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.INCOMPATIBLE
|
||||
import org.jetbrains.kotlin.resolve.scopes.KtScope
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeIntersector
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.oneMoreSpecificThanAnother
|
||||
|
||||
@@ -74,7 +75,7 @@ object OverloadUtil {
|
||||
val classifier = constructor.declarationDescriptor
|
||||
return when (classifier) {
|
||||
is ClassDescriptor -> this
|
||||
is TypeParameterDescriptor -> classifier.upperBoundsAsType
|
||||
is TypeParameterDescriptor -> TypeIntersector.getUpperBoundsAsType(classifier)
|
||||
else -> error("Unknown type constructor: $this")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,9 +40,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
||||
import org.jetbrains.kotlin.types.Variance.IN_VARIANCE
|
||||
import org.jetbrains.kotlin.types.Variance.OUT_VARIANCE
|
||||
import org.jetbrains.kotlin.types.Variance.*
|
||||
|
||||
public class TypeResolver(
|
||||
private val annotationResolver: AnnotationResolver,
|
||||
@@ -323,12 +321,10 @@ public class TypeResolver(
|
||||
}
|
||||
|
||||
private fun getScopeForTypeParameter(c: TypeResolutionContext, typeParameterDescriptor: TypeParameterDescriptor): KtScope {
|
||||
if (c.checkBounds) {
|
||||
return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope()
|
||||
}
|
||||
else {
|
||||
return LazyScopeAdapter(LockBasedStorageManager.NO_LOCKS.createLazyValue {
|
||||
typeParameterDescriptor.getUpperBoundsAsType().getMemberScope()
|
||||
return when {
|
||||
c.checkBounds -> TypeIntersector.getUpperBoundsAsType(typeParameterDescriptor).memberScope
|
||||
else -> LazyScopeAdapter(LockBasedStorageManager.NO_LOCKS.createLazyValue {
|
||||
TypeIntersector.getUpperBoundsAsType(typeParameterDescriptor).memberScope
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +88,9 @@ public fun CallableDescriptor.hasInferredReturnType(constraintSystem: Constraint
|
||||
|
||||
public fun getErasedReceiverType(receiverParameterDescriptor: ReceiverParameterDescriptor, descriptor: CallableDescriptor): KotlinType {
|
||||
var receiverType = receiverParameterDescriptor.getType()
|
||||
for (typeParameter in descriptor.getTypeParameters()) {
|
||||
if (typeParameter.getTypeConstructor() == receiverType.getConstructor()) {
|
||||
receiverType = typeParameter.getUpperBoundsAsType()
|
||||
for (typeParameter in descriptor.typeParameters) {
|
||||
if (typeParameter.typeConstructor == receiverType.constructor) {
|
||||
receiverType = TypeIntersector.getUpperBoundsAsType(typeParameter)
|
||||
}
|
||||
}
|
||||
val fakeTypeArguments = ContainerUtil.newSmartList<TypeProjection>()
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public class ConstraintsUtil {
|
||||
return type;
|
||||
}
|
||||
//todo may be error type
|
||||
return typeParameter.getUpperBoundsAsType();
|
||||
return TypeIntersector.getUpperBoundsAsType(typeParameter);
|
||||
}
|
||||
|
||||
public static boolean checkUpperBoundIsSatisfied(
|
||||
|
||||
-1
@@ -119,7 +119,6 @@ public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescri
|
||||
getOriginal();
|
||||
ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
|
||||
ForceResolveUtil.forceResolveAllContents(getUpperBounds());
|
||||
getUpperBoundsAsType();
|
||||
getVariance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class BoundsSubstitutor {
|
||||
|
||||
// todo assert: no loops
|
||||
for (TypeParameterDescriptor descriptor : topologicallySortTypeParameters(typeParameters)) {
|
||||
KotlinType upperBoundsAsType = descriptor.getUpperBoundsAsType();
|
||||
KotlinType upperBoundsAsType = TypeIntersector.getUpperBoundsAsType(descriptor);
|
||||
KotlinType substitutedUpperBoundsAsType = substitutor.substitute(upperBoundsAsType, Variance.INVARIANT);
|
||||
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjectionImpl(substitutedUpperBoundsAsType));
|
||||
}
|
||||
|
||||
@@ -33,9 +33,6 @@ public interface TypeParameterDescriptor extends ClassifierDescriptor {
|
||||
@NotNull
|
||||
List<KotlinType> getUpperBounds();
|
||||
|
||||
@NotNull
|
||||
KotlinType getUpperBoundsAsType();
|
||||
|
||||
@NotNull
|
||||
List<KotlinType> getLowerBounds();
|
||||
|
||||
|
||||
-22
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.scopes.LazyScopeAdapter;
|
||||
import org.jetbrains.kotlin.storage.NotNullLazyValue;
|
||||
import org.jetbrains.kotlin.storage.StorageManager;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -50,7 +49,6 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
||||
private final NotNullLazyValue<TypeConstructor> typeConstructor;
|
||||
private final NotNullLazyValue<KotlinType> defaultType;
|
||||
private final NotNullLazyValue<List<KotlinType>> upperBounds;
|
||||
private final NotNullLazyValue<KotlinType> upperBoundsAsType;
|
||||
|
||||
protected AbstractTypeParameterDescriptor(
|
||||
@NotNull final StorageManager storageManager,
|
||||
@@ -104,12 +102,6 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
||||
return resolveUpperBounds();
|
||||
}
|
||||
}, FALLBACK_UPPER_BOUNDS_ON_RECURSION);
|
||||
this.upperBoundsAsType = storageManager.createLazyValue(new Function0<KotlinType>() {
|
||||
@Override
|
||||
public KotlinType invoke() {
|
||||
return computeUpperBoundsAsType();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -140,20 +132,6 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
||||
return upperBounds.invoke();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public KotlinType getUpperBoundsAsType() {
|
||||
return upperBoundsAsType.invoke();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private KotlinType computeUpperBoundsAsType() {
|
||||
List<KotlinType> upperBounds = getUpperBounds();
|
||||
assert !upperBounds.isEmpty() : "Upper bound list is empty in " + getName();
|
||||
KotlinType upperBoundsAsType = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, upperBounds);
|
||||
return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(this).getNothingType();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeConstructor getTypeConstructor() {
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImplKt.registerTypeVariables;
|
||||
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.SPECIAL;
|
||||
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns;
|
||||
|
||||
public class TypeIntersector {
|
||||
|
||||
@@ -139,7 +140,20 @@ public class TypeIntersector {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO : check intersectibility, don't use a chanied scope
|
||||
/**
|
||||
* Note: this method was used in overload and override bindings to approximate type parameters with several bounds,
|
||||
* but as it turned out at some point, that logic was inconsistent with Java rules, so it was simplified.
|
||||
* Most of the other usages of this method are left untouched but probably should be investigated closely if they're still valid.
|
||||
*/
|
||||
@NotNull
|
||||
public static KotlinType getUpperBoundsAsType(@NotNull TypeParameterDescriptor descriptor) {
|
||||
List<KotlinType> upperBounds = descriptor.getUpperBounds();
|
||||
assert !upperBounds.isEmpty() : "Upper bound list is empty: " + descriptor;
|
||||
KotlinType upperBoundsAsType = intersectTypes(KotlinTypeChecker.DEFAULT, upperBounds);
|
||||
return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(descriptor).getNothingType();
|
||||
}
|
||||
|
||||
// TODO: check intersectability, don't use a chained scope
|
||||
private static class IntersectionScope extends ChainedScope {
|
||||
public IntersectionScope(@NotNull TypeConstructor constructor, @NotNull KtScope[] scopes) {
|
||||
super(null, "member scope for intersection type " + constructor, scopes);
|
||||
|
||||
@@ -47,7 +47,7 @@ fun FuzzyType.isAlmostEverything(): Boolean {
|
||||
if (freeParameters.isEmpty()) return false
|
||||
val typeParameter = type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
|
||||
if (typeParameter !in freeParameters) return false
|
||||
return typeParameter.upperBoundsAsType.isAnyOrNullableAny()
|
||||
return typeParameter.upperBounds.singleOrNull()?.isAnyOrNullableAny() ?: false
|
||||
}
|
||||
|
||||
class FuzzyType(
|
||||
|
||||
@@ -21,17 +21,14 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.getClassDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.substitutions.getTypeSubstitution
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import java.util.*
|
||||
@@ -60,7 +57,7 @@ class KotlinPullUpData(val sourceClass: KtClassOrObject,
|
||||
val substitution = LinkedHashMap<TypeConstructor, TypeProjection>()
|
||||
|
||||
typeParametersInSourceClassContext.forEach {
|
||||
substitution[it.typeConstructor] = TypeProjectionImpl(it.upperBoundsAsType)
|
||||
substitution[it.typeConstructor] = TypeProjectionImpl(TypeIntersector.getUpperBoundsAsType(it))
|
||||
}
|
||||
|
||||
val superClassSubstitution = getTypeSubstitution(targetClassDescriptor.defaultType, sourceClassDescriptor.defaultType)
|
||||
@@ -77,4 +74,4 @@ class KotlinPullUpData(val sourceClass: KtClassOrObject,
|
||||
}
|
||||
|
||||
val isInterfaceTarget: Boolean = targetClassDescriptor.kind == ClassKind.INTERFACE
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user