[NI] Disable capturing/approximation type in TypeSubstitutor with enabled NI

There is added a new service named `SubstitutingScopeProvider`, that
  provides factory that creates captured types and approximator for them.
  In OI they are the same as before commit, for NI they are empty, because
  that approximation interferes with NI algorithm

That service is injected into function descriptors and property descriptors
  and used for creating `SubstitutingScope` with correct services

Also there is changed time when we approximate captured types in NI
  (after all call checkers)

#KT-25290 Fixed
This commit is contained in:
Dmitriy Novozhilov
2019-05-16 14:51:17 +03:00
parent f47aafc471
commit f20ec3e0a6
80 changed files with 864 additions and 171 deletions
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.scopes.InnerClassesScopeWrapper;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope;
import org.jetbrains.kotlin.storage.NotNullLazyValue;
import org.jetbrains.kotlin.storage.StorageManager;
import org.jetbrains.kotlin.types.*;
@@ -34,10 +33,11 @@ import java.util.List;
public abstract class AbstractClassDescriptor implements ClassDescriptor {
private final Name name;
protected final NotNullLazyValue<SimpleType> defaultType;
protected final SubstitutingScopeProvider substitutingScopeProvider;
private final NotNullLazyValue<MemberScope> unsubstitutedInnerClassesScope;
private final NotNullLazyValue<ReceiverParameterDescriptor> thisAsReceiverParameter;
public AbstractClassDescriptor(@NotNull StorageManager storageManager, @NotNull Name name) {
public AbstractClassDescriptor(@NotNull StorageManager storageManager, @NotNull Name name, @NotNull SubstitutingScopeProvider substitutingScopeProvider) {
this.name = name;
this.defaultType = storageManager.createLazyValue(new Function0<SimpleType>() {
@Override
@@ -57,6 +57,11 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor {
return new LazyClassReceiverParameterDescriptor(AbstractClassDescriptor.this);
}
});
this.substitutingScopeProvider = substitutingScopeProvider;
}
public AbstractClassDescriptor(@NotNull StorageManager storageManager, @NotNull Name name) {
this(storageManager, name, SubstitutingScopeProvider.Companion.getDEFAULT());
}
@NotNull
@@ -92,7 +97,7 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor {
if (typeArguments.isEmpty()) return getUnsubstitutedMemberScope();
TypeSubstitutor substitutor = TypeConstructorSubstitution.create(getTypeConstructor(), typeArguments).buildSubstitutor();
return new SubstitutingScope(getUnsubstitutedMemberScope(), substitutor);
return substitutingScopeProvider.createSubstitutingScope(getUnsubstitutedMemberScope(), substitutor);
}
@NotNull
@@ -101,7 +106,7 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor {
if (typeSubstitution.isEmpty()) return getUnsubstitutedMemberScope();
TypeSubstitutor substitutor = TypeSubstitutor.create(typeSubstitution);
return new SubstitutingScope(getUnsubstitutedMemberScope(), substitutor);
return substitutingScopeProvider.createSubstitutingScope(getUnsubstitutedMemberScope(), substitutor);
}
@NotNull
@@ -110,7 +115,7 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor {
if (substitutor.isEmpty()) {
return this;
}
return new LazySubstitutingClassDescriptor(this, substitutor);
return new LazySubstitutingClassDescriptor(this, substitutor, substitutingScopeProvider);
}
@NotNull
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.SourceElement;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.storage.StorageManager;
import org.jetbrains.kotlin.types.SubstitutingScopeProvider;
public abstract class ClassDescriptorBase extends AbstractClassDescriptor {
@@ -35,7 +36,18 @@ public abstract class ClassDescriptorBase extends AbstractClassDescriptor {
@NotNull SourceElement source,
boolean isExternal
) {
super(storageManager, name);
this(storageManager, containingDeclaration, name, source, isExternal, SubstitutingScopeProvider.Companion.getDEFAULT());
}
protected ClassDescriptorBase(
@NotNull StorageManager storageManager,
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull Name name,
@NotNull SourceElement source,
boolean isExternal,
@NotNull SubstitutingScopeProvider substitutingScopeProvider
) {
super(storageManager, name, substitutingScopeProvider);
this.containingDeclaration = containingDeclaration;
this.source = source;
this.isExternal = isExternal;
@@ -324,11 +324,21 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
}
@Override
@Nullable
public FunctionDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor) {
return substitute(originalSubstitutor, SubstitutingScopeProvider.Companion.getDEFAULT());
}
@Nullable
public FunctionDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor, SubstitutingScopeProvider substitutingScopeProvider) {
if (originalSubstitutor.isEmpty()) {
return this;
}
return newCopyBuilder(originalSubstitutor).setOriginal(getOriginal()).setJustForTypeSubstitution(true).build();
return newCopyBuilder(originalSubstitutor)
.setOriginal(getOriginal())
.setJustForTypeSubstitution(true)
.setSubstitutingScopeProvider(substitutingScopeProvider)
.build();
}
@Nullable
@@ -365,6 +375,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
private Map<UserDataKey<?>, Object> userDataMap = new LinkedHashMap<UserDataKey<?>, Object>();
private Boolean newHasSynthesizedParameterNames = null;
protected boolean justForTypeSubstitution = false;
protected @NotNull SubstitutingScopeProvider substitutingScopeProvider;
public CopyConfiguration(
@NotNull TypeSubstitution substitution,
@@ -386,6 +397,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
this.newExtensionReceiverParameter = newExtensionReceiverParameter;
this.newReturnType = newReturnType;
this.name = name;
substitutingScopeProvider = SubstitutingScopeProvider.Companion.getDEFAULT();
}
@Override
@@ -554,6 +566,12 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
justForTypeSubstitution = value;
return this;
}
@NotNull
public CopyConfiguration setSubstitutingScopeProvider(@NotNull SubstitutingScopeProvider substitutingScopeProvider) {
this.substitutingScopeProvider = substitutingScopeProvider;
return this;
}
}
@Override
@@ -591,7 +609,8 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
List<TypeParameterDescriptor> substitutedTypeParameters =
new ArrayList<TypeParameterDescriptor>(unsubstitutedTypeParameters.size());
final TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
unsubstitutedTypeParameters, configuration.substitution, substitutedDescriptor, substitutedTypeParameters, wereChanges
unsubstitutedTypeParameters, configuration.substitution, substitutedDescriptor, substitutedTypeParameters,
wereChanges, configuration.substitutingScopeProvider
);
if (substitutor == null) return null;
@@ -28,10 +28,12 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
private List<TypeParameterDescriptor> typeConstructorParameters;
private List<TypeParameterDescriptor> declaredTypeParameters;
private TypeConstructor typeConstructor;
private final SubstitutingScopeProvider substitutingScopeProvider;
public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, TypeSubstitutor substitutor) {
public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, TypeSubstitutor substitutor, SubstitutingScopeProvider substitutingScopeProvider) {
this.original = descriptor;
this.originalSubstitutor = substitutor;
this.substitutingScopeProvider = substitutingScopeProvider;
}
private TypeSubstitutor getSubstitutor() {
@@ -87,7 +89,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
if (originalSubstitutor.isEmpty()) {
return memberScope;
}
return new SubstitutingScope(memberScope, getSubstitutor());
return substitutingScopeProvider.createSubstitutingScope(memberScope, getSubstitutor());
}
@NotNull
@@ -97,7 +99,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
if (originalSubstitutor.isEmpty()) {
return memberScope;
}
return new SubstitutingScope(memberScope, getSubstitutor());
return substitutingScopeProvider.createSubstitutingScope(memberScope, getSubstitutor());
}
@NotNull
@@ -107,7 +109,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
if (originalSubstitutor.isEmpty()) {
return memberScope;
}
return new SubstitutingScope(memberScope, getSubstitutor());
return substitutingScopeProvider.createSubstitutingScope(memberScope, getSubstitutor());
}
@NotNull
@@ -175,7 +177,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
@Override
public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
if (substitutor.isEmpty()) return this;
return new LazySubstitutingClassDescriptor(this, TypeSubstitutor.createChainedSubstitutor(substitutor.getSubstitution(), getSubstitutor().getSubstitution()));
return new LazySubstitutingClassDescriptor(this, TypeSubstitutor.createChainedSubstitutor(substitutor.getSubstitution(), getSubstitutor().getSubstitution()), substitutingScopeProvider);
}
@Override
@@ -47,6 +47,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
private final boolean isExternal;
private final boolean isDelegated;
private final SubstitutingScopeProvider substitutingScopeProvider;
private ReceiverParameterDescriptor dispatchReceiverParameter;
private ReceiverParameterDescriptor extensionReceiverParameter;
private List<TypeParameterDescriptor> typeParameters;
@@ -72,6 +74,28 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
boolean isActual,
boolean isExternal,
boolean isDelegated
) {
this(containingDeclaration, original, annotations, modality, visibility, isVar, name, kind, source,
lateInit, isConst, isExpect, isActual, isExternal, isDelegated, SubstitutingScopeProvider.Companion.getDEFAULT());
}
protected PropertyDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@Nullable PropertyDescriptor original,
@NotNull Annotations annotations,
@NotNull Modality modality,
@NotNull Visibility visibility,
boolean isVar,
@NotNull Name name,
@NotNull Kind kind,
@NotNull SourceElement source,
boolean lateInit,
boolean isConst,
boolean isExpect,
boolean isActual,
boolean isExternal,
boolean isDelegated,
@NotNull SubstitutingScopeProvider substitutingScopeProvider
) {
super(containingDeclaration, annotations, name, null, isVar, source);
this.modality = modality;
@@ -84,6 +108,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
this.isActual = isActual;
this.isExternal = isExternal;
this.isDelegated = isDelegated;
this.substitutingScopeProvider = substitutingScopeProvider;
}
@NotNull
@@ -102,10 +127,39 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
boolean isActual,
boolean isExternal,
boolean isDelegated
) {
return create(containingDeclaration, annotations, modality, visibility, isVar, name, kind, source,
lateInit, isConst, isExpect, isActual, isExternal, isDelegated, SubstitutingScopeProvider.Companion.getDEFAULT());
}
@NotNull
public static PropertyDescriptorImpl create(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull Annotations annotations,
@NotNull Modality modality,
@NotNull Visibility visibility,
boolean isVar,
@NotNull Name name,
@NotNull Kind kind,
@NotNull SourceElement source,
boolean lateInit,
boolean isConst,
boolean isExpect,
boolean isActual,
boolean isExternal,
boolean isDelegated,
@NotNull SubstitutingScopeProvider substitutingScopeProvider
) {
return new PropertyDescriptorImpl(containingDeclaration, null, annotations,
modality, visibility, isVar, name, kind, source, lateInit, isConst,
isExpect, isActual, isExternal, isDelegated);
isExpect, isActual, isExternal, isDelegated, substitutingScopeProvider);
}
@NotNull
public PropertyDescriptorImpl getCopy() {
return new PropertyDescriptorImpl(getContainingDeclaration(), original, getAnnotations(),
modality, visibility, isVar(), getName(), kind, getSource(), lateInit, isConst,
isExpect, isActual, isExternal, isDelegated, substitutingScopeProvider);
}
public void setType(
@@ -258,6 +312,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
private ReceiverParameterDescriptor dispatchReceiverParameter = PropertyDescriptorImpl.this.dispatchReceiverParameter;
private List<TypeParameterDescriptor> newTypeParameters = null;
private Name name = getName();
private boolean setterProjectedOut = PropertyDescriptorImpl.this.setterProjectedOut;
@NotNull
@Override
@@ -364,6 +419,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
originalTypeParameters, copyConfiguration.substitution, substitutedDescriptor, substitutedTypeParameters
);
substitutor.setSubstitutingScopeProvider(substitutingScopeProvider);
KotlinType originalOutType = getType();
KotlinType outType = substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
@@ -460,6 +516,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
substitutedDescriptor.setCompileTimeInitializer(compileTimeInitializer);
}
substitutedDescriptor.setterProjectedOut = copyConfiguration.setterProjectedOut;
return substitutedDescriptor;
}
@@ -470,7 +528,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
return prev;
}
private static FunctionDescriptor getSubstitutedInitialSignatureDescriptor(
public static FunctionDescriptor getSubstitutedInitialSignatureDescriptor(
@NotNull TypeSubstitutor substitutor,
@NotNull PropertyAccessorDescriptor accessorDescriptor
) {
@@ -490,7 +548,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
) {
return new PropertyDescriptorImpl(
newOwner, original, getAnnotations(), newModality, newVisibility, isVar(), newName, kind, SourceElement.NO_SOURCE,
isLateInit(), isConst(), isExpect(), isActual(), isExternal(), isDelegated()
isLateInit(), isConst(), isExpect(), isActual(), isExternal(), isDelegated(), substitutingScopeProvider
);
}
@@ -564,4 +622,9 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
public <V> V getUserData(UserDataKey<V> key) {
return null;
}
@NotNull
public SubstitutingScopeProvider getSubstitutingScopeProvider() {
return substitutingScopeProvider;
}
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.join
open class ValueParameterDescriptorImpl(
@@ -102,8 +103,7 @@ open class ValueParameterDescriptorImpl(
override fun getOriginal() = if (original === this) this else original.original
override fun substitute(substitutor: TypeSubstitutor): ValueParameterDescriptor {
if (substitutor.isEmpty) return this
throw UnsupportedOperationException() // TODO
return this
}
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R {
@@ -100,16 +100,25 @@ class CapturedType(
CapturedType(typeProjection, constructor, isMarkedNullable, newAnnotations)
}
object OldCapturedTypeCreator : CapturedTypeCreator {
override fun createCapturedType(typeProjection: TypeProjection): TypeProjection {
return TypeProjectionImpl(CapturedType(typeProjection))
}
}
fun createCapturedType(typeProjection: TypeProjection): KotlinType = CapturedType(typeProjection)
fun KotlinType.isCaptured(): Boolean = constructor is CapturedTypeConstructor
fun TypeSubstitution.wrapWithCapturingSubstitution(needApproximation: Boolean = true): TypeSubstitution =
fun TypeSubstitution.wrapWithCapturingSubstitution(
capturedTypeCreator: CapturedTypeCreator = OldCapturedTypeCreator,
needApproximation: Boolean = true
): TypeSubstitution =
if (this is IndexedParametersSubstitution)
IndexedParametersSubstitution(
this.parameters,
this.arguments.zip(this.parameters).map {
it.first.createCapturedIfNeeded(it.second)
it.first.createCapturedIfNeeded(it.second, capturedTypeCreator)
}.toTypedArray(),
approximateCapturedTypes = needApproximation
)
@@ -117,10 +126,16 @@ fun TypeSubstitution.wrapWithCapturingSubstitution(needApproximation: Boolean =
object : DelegatedTypeSubstitution(this@wrapWithCapturingSubstitution) {
override fun approximateContravariantCapturedTypes() = needApproximation
override fun get(key: KotlinType) =
super.get(key)?.createCapturedIfNeeded(key.constructor.declarationDescriptor as? TypeParameterDescriptor)
super.get(key)?.createCapturedIfNeeded(
key.constructor.declarationDescriptor as? TypeParameterDescriptor,
capturedTypeCreator
)
}
private fun TypeProjection.createCapturedIfNeeded(typeParameterDescriptor: TypeParameterDescriptor?): TypeProjection {
private fun TypeProjection.createCapturedIfNeeded(
typeParameterDescriptor: TypeParameterDescriptor?,
capturedTypeCreator: CapturedTypeCreator
): TypeProjection {
if (typeParameterDescriptor == null || projectionKind == Variance.INVARIANT) return this
// Treat consistent projections as invariant
@@ -134,5 +149,5 @@ private fun TypeProjection.createCapturedIfNeeded(typeParameterDescriptor: TypeP
TypeProjectionImpl(this@createCapturedIfNeeded.type)
}
return TypeProjectionImpl(createCapturedType(this))
return capturedTypeCreator.createCapturedType(this)
}
@@ -18,18 +18,24 @@ package org.jetbrains.kotlin.resolve.scopes
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.Substitutable
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.SubstitutingScopeProvider
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
import org.jetbrains.kotlin.utils.sure
import java.util.*
class SubstitutingScope(private val workerScope: MemberScope, givenSubstitutor: TypeSubstitutor) : MemberScope {
class SubstitutingScope(private val workerScope: MemberScope, givenSubstitutor: TypeSubstitutor, private val substitutingScopeProvider: SubstitutingScopeProvider) : MemberScope {
private val substitutor = givenSubstitutor.substitution.wrapWithCapturingSubstitution().buildSubstitutor()
private val substitutor: TypeSubstitutor = givenSubstitutor.substitution
.wrapWithCapturingSubstitution(capturedTypeCreator = substitutingScopeProvider.provideCapturedTypeCreator())
.buildSubstitutor().also { it.setSubstitutingScopeProvider(substitutingScopeProvider) }
private var substitutedDescriptors: MutableMap<DeclarationDescriptor, DeclarationDescriptor>? = null
@@ -43,11 +49,44 @@ class SubstitutingScope(private val workerScope: MemberScope, givenSubstitutor:
}
val substituted = substitutedDescriptors!!.getOrPut(descriptor) {
val assertionMessage = {
"We expect that no conflict should happen while substitution is guaranteed to generate invariant projection, " +
"but $descriptor substitution fails"
}
when (descriptor) {
is Substitutable<*> -> descriptor.substitute(substitutor).sure {
"We expect that no conflict should happen while substitution is guaranteed to generate invariant projection, " +
"but $descriptor substitution fails"
/*
* Here we can take null if NI enabled, because inside this place we have OI and NI collide. See following example:
*
* class Out<out T>
*
* class A<T> {
* fun T.foo() {}
* fun Out<T>.bar() {}
* }
*
* fun test(x: A<out CharSequence>, y: Out<CharSequence>) {
* with(x) {
* "".foo() <-- problem is here
* }
* }
*
* Because of we don't capture type projections, in call "".foo() we have `out CharSequence` as substituted type `T`
* (instead of `CapturedType(out CharSequence)`, and `in String` as type from receiver, so we have type variance error
* and can not substitute descriptor.
*
* So, fix of it is hack
*/
is FunctionDescriptorImpl -> {
val substitutedDescriptor = descriptor.substitute(substitutor, substitutingScopeProvider)
if (substitutingScopeProvider.isNewInferenceEnabled) {
substitutedDescriptor ?: ErrorUtils.createErrorScope("Cannot substitute functional descriptor")
.getContributedFunctions(descriptor.name, NoLookupLocation.WHEN_RESOLVE_DECLARATION).first()
} else {
substitutedDescriptor.sure(assertionMessage)
}
}
is Substitutable<*> -> descriptor.substitute(substitutor).sure(assertionMessage)
else -> error("Unknown descriptor in scope: $descriptor")
}
}
@@ -72,7 +111,7 @@ class SubstitutingScope(private val workerScope: MemberScope, givenSubstitutor:
override fun getContributedVariables(name: Name, location: LookupLocation) = substitute(workerScope.getContributedVariables(name, location))
override fun getContributedClassifier(name: Name, location: LookupLocation) =
workerScope.getContributedClassifier(name, location)?.let { substitute(it) }
workerScope.getContributedClassifier(name, location)?.let { substitute(it) }
override fun getContributedFunctions(name: Name, location: LookupLocation) = substitute(workerScope.getContributedFunctions(name, location))
@@ -28,6 +28,12 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.builtIns
import java.util.*
class OldCaptureTypeApproximator : CapturedTypeApproximator {
override fun approximateCapturedTypes(typeProjection: TypeProjection?, approximateContravariant: Boolean): TypeProjection? {
return approximateCapturedTypesIfNecessary(typeProjection, approximateContravariant)
}
}
data class ApproximationBounds<out T>(
val lower: T,
val upper: T
@@ -40,7 +40,7 @@ public class DescriptorSubstitutor {
@NotNull DeclarationDescriptor newContainingDeclaration,
@NotNull @Mutable List<TypeParameterDescriptor> result
) {
TypeSubstitutor substitutor = substituteTypeParameters(typeParameters, originalSubstitution, newContainingDeclaration, result, null);
TypeSubstitutor substitutor = substituteTypeParameters(typeParameters, originalSubstitution, newContainingDeclaration, result, null, SubstitutingScopeProvider.Companion.getDEFAULT());
if (substitutor == null) throw new AssertionError("Substitution failed");
return substitutor;
}
@@ -51,7 +51,8 @@ public class DescriptorSubstitutor {
@NotNull TypeSubstitution originalSubstitution,
@NotNull DeclarationDescriptor newContainingDeclaration,
@NotNull @Mutable List<TypeParameterDescriptor> result,
@Nullable boolean[] wereChanges
@Nullable boolean[] wereChanges,
@NotNull SubstitutingScopeProvider substitutingScopeProvider
) {
Map<TypeConstructor, TypeProjection> mutableSubstitution = new HashMap<TypeConstructor, TypeProjection>();
@@ -76,7 +77,7 @@ public class DescriptorSubstitutor {
TypeSubstitutor substitutor = TypeSubstitutor.createChainedSubstitutor(
originalSubstitution, TypeConstructorSubstitution.createByConstructorsMap(mutableSubstitution)
);
).setSubstitutingScopeProvider(substitutingScopeProvider);
for (TypeParameterDescriptor descriptor : typeParameters) {
TypeParameterDescriptorImpl substituted = substitutedMap.get(descriptor);
@@ -0,0 +1,47 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.resolve.calls.inference.OldCapturedTypeCreator
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope
import org.jetbrains.kotlin.types.typesApproximation.OldCaptureTypeApproximator
interface SubstitutingScopeProvider {
fun createSubstitutingScope(workerScope: MemberScope, givenSubstitutor: TypeSubstitutor): SubstitutingScope
fun provideCapturedTypeCreator(): CapturedTypeCreator
fun provideApproximator(): CapturedTypeApproximator
val isNewInferenceEnabled: Boolean
companion object {
val DEFAULT: SubstitutingScopeProvider = object : SubstitutingScopeProvider {
override fun createSubstitutingScope(workerScope: MemberScope, givenSubstitutor: TypeSubstitutor): SubstitutingScope {
return SubstitutingScope(workerScope, givenSubstitutor, this)
}
override fun provideCapturedTypeCreator(): CapturedTypeCreator {
return OldCapturedTypeCreator
}
override fun provideApproximator(): CapturedTypeApproximator {
return OldCaptureTypeApproximator()
}
override val isNewInferenceEnabled: Boolean get() = false
}
}
}
interface CapturedTypeCreator {
fun createCapturedType(typeProjection: TypeProjection): TypeProjection
}
interface CapturedTypeApproximator {
fun approximateCapturedTypes(typeProjection: TypeProjection?, approximateContravariant: Boolean): TypeProjection?
}
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructorKt;
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import java.util.ArrayList;
@@ -47,6 +46,14 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
}
}
private @NotNull SubstitutingScopeProvider substitutingScopeProvider;
@NotNull
public TypeSubstitutor setSubstitutingScopeProvider(@NotNull SubstitutingScopeProvider substitutingScopeProvider) {
this.substitutingScopeProvider = substitutingScopeProvider;
return this;
}
@NotNull
public static TypeSubstitutor create(@NotNull TypeSubstitution substitution) {
return new TypeSubstitutor(substitution);
@@ -73,6 +80,7 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
protected TypeSubstitutor(@NotNull TypeSubstitution substitution) {
this.substitution = substitution;
this.substitutingScopeProvider = SubstitutingScopeProvider.Companion.getDEFAULT();
}
public boolean isEmpty() {
@@ -110,8 +118,12 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
if (!substitution.approximateCapturedTypes() && !substitution.approximateContravariantCapturedTypes()) {
return substitutedTypeProjection;
}
return CapturedTypeApproximationKt.approximateCapturedTypesIfNecessary(
substitutedTypeProjection, substitution.approximateContravariantCapturedTypes());
CapturedTypeApproximator approximator = substitutingScopeProvider.provideApproximator();
return approximator.approximateCapturedTypes(
substitutedTypeProjection,
substitution.approximateContravariantCapturedTypes()
);
}
@Nullable
@@ -55,6 +55,11 @@ public class TypeUtils {
throw new IllegalStateException(name);
}
@Override
public boolean isMarkedNullable() {
return false;
}
@NotNull
@Override
public String toString() {
@@ -521,6 +521,10 @@ internal fun UnwrappedType.typeDepthInternal() =
internal fun SimpleType.typeDepthInternal(): Int {
if (this is TypeUtils.SpecialType) return 0
if (this is NewCapturedType) {
return constructor.projection.type.unwrap().typeDepthInternal()
}
val maxInArguments = arguments.asSequence().map {
if (it.isStarProjection) 1 else it.type.unwrap().typeDepthInternal()
}.max() ?: 0