Fix race in IDE: inject proper storage manager for type parameters

With NO_LOCKS strategy we can easily end up in a situation when
 constraint system for a generic call is built incorrectly,
 producing flaky errors (or don't produce errors at all)

 Now proper storage manager is injected for all cases except:
 - IR
 - Codegen
 - Serialization plugin
 - Fake local objects

 Most likely, NO_LOCKS strategy for these cases is fine as at that point
 the compiler works in one thread

 #KT-34786 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2019-11-25 17:12:28 +03:00
parent 399667a434
commit eb73650209
21 changed files with 103 additions and 40 deletions
@@ -60,7 +60,7 @@ class FunctionClassDescriptor(
fun typeParameter(variance: Variance, name: String) {
result.add(TypeParameterDescriptorImpl.createWithDefaultBound(
this@FunctionClassDescriptor, Annotations.EMPTY, false, variance, Name.identifier(name), result.size
this@FunctionClassDescriptor, Annotations.EMPTY, false, variance, Name.identifier(name), result.size, storageManager
))
}
@@ -31,7 +31,7 @@ private val FAKE_CONTINUATION_CLASS_DESCRIPTOR_EXPERIMENTAL =
visibility = Visibilities.PUBLIC
setTypeParameterDescriptors(
TypeParameterDescriptorImpl.createWithDefaultBound(
this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0
this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0, LockBasedStorageManager.NO_LOCKS
).let(::listOf)
)
createTypeConstructor()
@@ -47,7 +47,7 @@ private val FAKE_CONTINUATION_CLASS_DESCRIPTOR_RELEASE =
visibility = Visibilities.PUBLIC
setTypeParameterDescriptors(
TypeParameterDescriptorImpl.createWithDefaultBound(
this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0
this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0, LockBasedStorageManager.NO_LOCKS
).let(::listOf)
)
createTypeConstructor()
@@ -53,7 +53,7 @@ class NotFoundClasses(private val storageManager: StorageManager, private val mo
) : ClassDescriptorBase(storageManager, container, name, SourceElement.NO_SOURCE, /* isExternal = */ false) {
private val typeParameters = (0 until numberOfDeclaredTypeParameters).map { index ->
TypeParameterDescriptorImpl.createWithDefaultBound(
this, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier("T$index"), index
this, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier("T$index"), index, storageManager
)
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.storage.StorageManager;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeConstructor;
import org.jetbrains.kotlin.types.Variance;
@@ -53,4 +54,7 @@ public interface TypeParameterDescriptor extends ClassifierDescriptor, TypeParam
* 3. 'getTypeConstructor' is the same as for original declaration (at least in means of 'equals')
*/
boolean isCapturedFromOuterDeclaration();
@NotNull
StorageManager getStorageManager();
}
@@ -42,6 +42,7 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
private final NotNullLazyValue<TypeConstructor> typeConstructor;
private final NotNullLazyValue<SimpleType> defaultType;
private final StorageManager storageManager;
protected AbstractTypeParameterDescriptor(
@NotNull final StorageManager storageManager,
@@ -82,6 +83,7 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
);
}
});
this.storageManager = storageManager;
}
protected abstract void reportSupertypeLoopError(@NotNull KotlinType type);
@@ -139,6 +141,12 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
return visitor.visitTypeParameterDescriptor(this, data);
}
@NotNull
@Override
public StorageManager getStorageManager() {
return storageManager;
}
private class TypeParameterTypeConstructor extends AbstractTypeConstructor {
private final SupertypeLoopChecker supertypeLoopChecker;
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
import org.jetbrains.kotlin.storage.StorageManager;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.KotlinTypeKt;
import org.jetbrains.kotlin.types.Variance;
@@ -47,10 +47,12 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
boolean reified,
@NotNull Variance variance,
@NotNull Name name,
int index
int index,
@NotNull StorageManager storageManager
) {
TypeParameterDescriptorImpl typeParameterDescriptor =
createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, SourceElement.NO_SOURCE);
TypeParameterDescriptorImpl typeParameterDescriptor = createForFurtherModification(
containingDeclaration, annotations, reified, variance, name, index, SourceElement.NO_SOURCE, storageManager
);
typeParameterDescriptor.addUpperBound(getBuiltIns(containingDeclaration).getDefaultBound());
typeParameterDescriptor.setInitialized();
return typeParameterDescriptor;
@@ -63,10 +65,13 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
@NotNull Variance variance,
@NotNull Name name,
int index,
@NotNull SourceElement source
@NotNull SourceElement source,
@NotNull StorageManager storageManager
) {
return createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, source,
/* reportSupertypeLoopError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE);
return createForFurtherModification(
containingDeclaration, annotations, reified, variance, name, index, source,
null, SupertypeLoopChecker.EMPTY.INSTANCE, storageManager
);
}
public static TypeParameterDescriptorImpl createForFurtherModification(
@@ -78,10 +83,13 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
int index,
@NotNull SourceElement source,
@Nullable Function1<KotlinType, Void> reportCycleError,
@NotNull SupertypeLoopChecker supertypeLoopsResolver
@NotNull SupertypeLoopChecker supertypeLoopsResolver,
@NotNull StorageManager storageManager
) {
return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index, source, reportCycleError,
supertypeLoopsResolver);
return new TypeParameterDescriptorImpl(
containingDeclaration, annotations, reified, variance, name,
index, source, reportCycleError, supertypeLoopsResolver, storageManager
);
}
private final List<KotlinType> upperBounds = new ArrayList<KotlinType>(1);
@@ -96,10 +104,10 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
int index,
@NotNull SourceElement source,
@Nullable Function1<KotlinType, Void> reportCycleError,
@NotNull SupertypeLoopChecker supertypeLoopsChecker
@NotNull SupertypeLoopChecker supertypeLoopsChecker,
@NotNull StorageManager storageManager
) {
super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, annotations, name, variance, reified, index, source,
supertypeLoopsChecker);
super(storageManager, containingDeclaration, annotations, name, variance, reified, index, source, supertypeLoopsChecker);
this.reportCycleError = reportCycleError;
}
@@ -40,7 +40,9 @@ 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
);
if (substitutor == null) throw new AssertionError("Substitution failed");
return substitutor;
}
@@ -65,7 +67,8 @@ public class DescriptorSubstitutor {
descriptor.getVariance(),
descriptor.getName(),
index++,
SourceElement.NO_SOURCE
SourceElement.NO_SOURCE,
descriptor.getStorageManager()
);
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjectionImpl(substituted.getDefaultType()));