addDependency
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableAccessorDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableAccessorDescriptor.kt
index d88db5e..bc56c6c 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableAccessorDescriptor.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/impl/LocalVariableAccessorDescriptor.kt
@@ -42,7 +42,7 @@
                 emptyList()
             } else {
                 val valueParameterDescriptorImpl = createValueParameter(Name.identifier("value"), correspondingVariable.type)
-                this.addInitFinalizationAction(valueParameterDescriptorImpl::finalizeInit)
+                addDependency(valueParameterDescriptorImpl)
                 listOf(valueParameterDescriptorImpl)
             }
         val returnType =
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingTraceContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingTraceContext.java
index c7c7336..51e4405 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingTraceContext.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingTraceContext.java
@@ -22,6 +22,7 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.kotlin.descriptors.InitializableDescriptor;
+import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorNonRootImpl;
 import org.jetbrains.kotlin.diagnostics.Diagnostic;
 import org.jetbrains.kotlin.psi.KtExpression;
 import org.jetbrains.kotlin.resolve.diagnostics.BindingContextSuppressCache;
@@ -169,7 +170,11 @@
         if (isValidationEnabled && value instanceof InitializableDescriptor) {
             boolean initialized = ((InitializableDescriptor) value).isInitFinalized();
             if (!initialized) {
-                throw new IllegalStateException(value + " is not fully initialized");
+                if (value instanceof DeclarationDescriptorNonRootImpl) {
+                    throw new IllegalStateException(value + " is not fully initialized", ((DeclarationDescriptorNonRootImpl) value).created);
+                } else {
+                    throw new IllegalStateException(value + " is not fully initialized");
+                }
             }
         }
     }
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DataClassDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DataClassDescriptorResolver.kt
index d491cd5..0ae3bcd 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DataClassDescriptorResolver.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DataClassDescriptorResolver.kt
@@ -20,10 +20,7 @@
 import org.jetbrains.kotlin.descriptors.annotations.Annotations
 import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
 import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
-import org.jetbrains.kotlin.incremental.components.NoLookupLocation
 import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
-import org.jetbrains.kotlin.util.OperatorNameConventions
 
 object DataClassDescriptorResolver {
     val COPY_METHOD_NAME = Name.identifier("copy")
@@ -88,6 +85,7 @@
                 functionDescriptor, null, parameter.index, parameter.annotations, parameter.name, parameter.type, declaresDefaultValue,
                 parameter.isCrossinline, parameter.isNoinline, parameter.varargElementType, parameter.source
             )
+            functionDescriptor.addDependency(parameterDescriptor)
             parameterDescriptors.add(parameterDescriptor)
             if (declaresDefaultValue) {
                 trace.record(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameterDescriptor, propertyDescriptor)
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java
index 69360ba..d8b9cd3 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java
@@ -490,12 +490,11 @@
                 supertypeLoopsResolver,
                 storageManager
         );
-        if (containingDescriptor instanceof DeclarationDescriptorNonRootImpl) {
-            ((DeclarationDescriptorNonRootImpl) containingDescriptor).addInitFinalizationAction(
-                    () -> {
-                        typeParameterDescriptor.finalizeInit();
-                        trace.record(BindingContext.TYPE_PARAMETER, typeParameter, typeParameterDescriptor);
-                    }
+        if (containingDescriptor instanceof InitializableDescriptor) {
+            InitializableDescriptor initializableDescriptor = (InitializableDescriptor) containingDescriptor;
+            initializableDescriptor.addDependency(typeParameterDescriptor);
+            initializableDescriptor.addInitFinalizationAction(
+                    () -> trace.record(BindingContext.TYPE_PARAMETER, typeParameter, typeParameterDescriptor)
             );
         } else {
             typeParameterDescriptor.finalizeInit();
@@ -945,6 +944,11 @@
                 modifierList != null && modifierList.hasModifier(KtTokens.EXTERNAL_KEYWORD),
                 propertyInfo.getHasDelegate()
         );
+        //if (container instanceof InitializableDescriptor) {
+        //    ((InitializableDescriptor) container).addDependency(propertyDescriptor);
+        //} else {
+        //    propertyDescriptor.finalizeInit();
+        //}
 
         List<TypeParameterDescriptorImpl> typeParameterDescriptors;
         LexicalScope scopeForDeclarationResolutionWithTypeParameters;
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt
index 3bc404c..67cc88d 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt
@@ -338,8 +338,8 @@
                     valueParameterDescriptor.isCrossinline, valueParameterDescriptor.isNoinline,
                     valueParameterDescriptor.varargElementType, SourceElement.NO_SOURCE
                 )
+                functionDescriptor.addDependency(it)
                 functionDescriptor.addInitFinalizationAction {
-                    it.finalizeInit()
                     trace.record(BindingContext.AUTO_CREATED_IT, it)
                 }
                 return listOf(it)
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt
index b4c6cf0..f70c338 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt
@@ -439,7 +439,8 @@
                 ) : VariableDescriptorImpl(containingDeclaration, annotations, name, type, source) {
                     init {
                         if (containingDeclaration is InitializableDescriptor) {
-                            containingDeclaration.addInitFinalizationAction(::finalizeInit)
+                            // TODO [VD]?
+                            containingDeclaration.addDependency(this)
                         } else {
                             finalizeInit()
                         }
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt
index 145b5c2..d2db420 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt
@@ -177,8 +177,8 @@
                 varargElementType,
                 SourceElement.NO_SOURCE
             )
-            if (owner is DeclarationDescriptorNonRootImpl) {
-                owner.addInitFinalizationAction(valueParameterDescriptorImpl::finalizeInit)
+            if (owner is InitializableDescriptor) {
+                owner.addDependency(valueParameterDescriptorImpl)
             } else {
                 valueParameterDescriptorImpl.finalizeInit()
             }
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java
index ae067c8..7d24beb 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java
@@ -624,10 +624,13 @@
             if (result != null) {
                 DeclarationDescriptor containingDeclaration = result.getContainingDeclaration();
                 // containingDeclaration could be non-finally initialized PropertyDescriptorImpl
-                //containingDeclaration.addInitFinalizationAction(
-                //        () ->
-                                context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), containingDeclaration);
-                //);
+                if (containingDeclaration instanceof InitializableDescriptor) {
+                    ((InitializableDescriptor) containingDeclaration).addInitFinalizationAction(
+                            () -> context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), containingDeclaration)
+                    );
+                } else {
+                    context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), containingDeclaration);
+                }
                 recordThisOrSuperCallInTraceAndCallExtension(context, result, expression);
             }
             return LabelResolver.LabeledReceiverResolutionResult.Companion.labelResolutionSuccess(result);
diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt
index 76111e0..d416f8e 100644
--- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt
+++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt
@@ -20,7 +20,10 @@
 import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME
 import org.jetbrains.kotlin.descriptors.*
 import org.jetbrains.kotlin.descriptors.annotations.Annotations
-import org.jetbrains.kotlin.descriptors.impl.*
+import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
+import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
+import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
+import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
 import org.jetbrains.kotlin.incremental.components.LookupLocation
 import org.jetbrains.kotlin.incremental.components.NoLookupLocation
 import org.jetbrains.kotlin.incremental.record
@@ -792,8 +795,8 @@
             varargElementType?.let { TypeUtils.makeNotNullable(it) },
             c.components.sourceElementFactory.source(method)
         )
-        if (constructor is DeclarationDescriptorNonRootImpl) {
-            constructor.addInitFinalizationAction(valueParameterDescriptor::finalizeInit)
+        if (constructor is InitializableDescriptor) {
+            constructor.addDependency(valueParameterDescriptor)
         } else {
             valueParameterDescriptor.finalizeInit()
         }
diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt
index 6fb9047..1acb5d4 100644
--- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt
+++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt
@@ -19,7 +19,6 @@
 import org.jetbrains.kotlin.builtins.KotlinBuiltIns
 import org.jetbrains.kotlin.descriptors.*
 import org.jetbrains.kotlin.descriptors.annotations.Annotations
-import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorNonRootImpl
 import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
 import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
 import org.jetbrains.kotlin.incremental.components.LookupLocation
@@ -254,8 +253,8 @@
                 varargElementType,
                 c.components.sourceElementFactory.source(javaParameter)
             )
-            if (function is DeclarationDescriptorNonRootImpl) {
-                function.addInitFinalizationAction(valueParameterDescriptorImpl::finalizeInit)
+            if (function is InitializableDescriptor) {
+                function.addDependency(valueParameterDescriptorImpl)
             } else {
                 valueParameterDescriptorImpl.finalizeInit()
             }
diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/InitializableDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/InitializableDescriptor.java
index c89f44e..4b9d601 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/InitializableDescriptor.java
+++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/InitializableDescriptor.java
@@ -15,5 +15,12 @@
      */
     void addInitFinalizationAction(@NotNull Runnable action);
 
+    /**
+     * @param dependency is a descriptor that depends on this descriptor.
+     */
+    void addDependency(@NotNull InitializableDescriptor dependency);
+
     boolean isInitFinalized();
+
+    void finalizeInit();
 }
diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/DeclarationDescriptorNonRootImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/DeclarationDescriptorNonRootImpl.java
index 4dd99c8..c3ff226 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/DeclarationDescriptorNonRootImpl.java
+++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/DeclarationDescriptorNonRootImpl.java
@@ -34,10 +34,11 @@
     @NotNull
     private final SourceElement source;
 
+    public final Exception created = new Exception();
+    private final Object initLock = new Object();
+    private volatile boolean initFinalized;
     private List<Runnable> initFinalizationActions;
-
-    private final Exception created = new Exception();
-    private boolean initFinalized;
+    private List<InitializableDescriptor> dependencies;
 
     protected DeclarationDescriptorNonRootImpl(
             @NotNull DeclarationDescriptor containingDeclaration,
@@ -81,24 +82,51 @@
         return source;
     }
 
+    @Override
     public final void finalizeInit() {
         if (containingDeclaration instanceof InitializableDescriptor && !((InitializableDescriptor)containingDeclaration).isInitFinalized()) {
-            throw new IllegalStateException("Initialization of " + containingDeclaration + " descriptor is finalized.");
+            throw new IllegalStateException(uninitializedMessage((InitializableDescriptor) containingDeclaration));
         }
-        if (initFinalized && allowReInitialization()) {
-            if (initFinalizationActions != null && !initFinalizationActions.isEmpty()) {
-                throw new IllegalStateException();
+        List<Runnable> finalizationActions;
+        List<InitializableDescriptor> dependencyList;
+        synchronized (initLock) {
+            finalizationActions = initFinalizationActions != null ? new ArrayList<>(initFinalizationActions) : null;
+            if (initFinalized && allowReInitialization()) {
+                if (finalizationActions != null && !finalizationActions.isEmpty()) {
+                    throw new IllegalStateException();
+                }
+                return;
             }
-            return;
-        }
 
-        checkInitNotFinalized();
-        initFinalized = true;
-        if (initFinalizationActions != null) {
-            for (Runnable action : initFinalizationActions) {
+            checkInitNotFinalized();
+            dependencyList = dependencies != null ? new ArrayList<>(dependencies) : null;
+
+            initFinalized = true;
+        }
+        if (dependencyList != null) {
+            for (InitializableDescriptor descriptor : dependencyList) {
+                descriptor.finalizeInit();
+            }
+        }
+        if (finalizationActions != null) {
+            for (Runnable action : finalizationActions) {
                 action.run();
             }
-            initFinalizationActions.clear();
+            finalizationActions.clear();
+        }
+    }
+
+    @Override
+    public void addDependency(@NotNull InitializableDescriptor dependency) {
+        if (initFinalized) {
+            dependency.finalizeInit();
+        } else {
+            synchronized (initLock) {
+                if (dependencies == null) {
+                    dependencies = new ArrayList<>();
+                }
+                dependencies.add(dependency);
+            }
         }
     }
 
@@ -107,10 +135,12 @@
         if (initFinalized) {
             action.run();
         } else {
-            if (initFinalizationActions == null) {
-                initFinalizationActions = new ArrayList<>();
+            synchronized (initLock) {
+                if (initFinalizationActions == null) {
+                    initFinalizationActions = new ArrayList<>();
+                }
+                initFinalizationActions.add(action);
             }
-            initFinalizationActions.add(action);
         }
     }
 
@@ -120,22 +150,22 @@
 
     protected void checkInitNotFinalized() {
         if (initFinalized) {
-            throw new IllegalStateException(initializedMessage(), created);
+            throw new IllegalStateException(initializedMessage(this), created);
         }
     }
 
     protected void checkInitFinalized() {
         if (!initFinalized) {
-            throw new IllegalStateException(uninitializedMessage());
+            throw new IllegalStateException(uninitializedMessage(this));
         }
     }
 
-    protected String initializedMessage() {
-        return "Initialization of " + this + " descriptor is finalized.";
+    private static String initializedMessage(InitializableDescriptor descriptor) {
+        return "Initialization of " + descriptor + " descriptor is finalized.";
     }
 
-    protected String uninitializedMessage() {
-        return "Initialization of " + this + " descriptor is not finalized.";
+    private static String uninitializedMessage(InitializableDescriptor descriptor) {
+        return "Initialization of " + descriptor + " descriptor is not finalized.";
     }
 
     @Override
diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertySetterDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertySetterDescriptorImpl.java
index 72d9334..23f9f9d 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertySetterDescriptorImpl.java
+++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertySetterDescriptorImpl.java
@@ -75,8 +75,8 @@
                 /* isNoinline = */ false,
                 null, SourceElement.NO_SOURCE
         );
-        if (setterDescriptor instanceof DeclarationDescriptorNonRootImpl) {
-            ((DeclarationDescriptorNonRootImpl) setterDescriptor).addInitFinalizationAction(descriptor::finalizeInit);
+        if (setterDescriptor instanceof InitializableDescriptor) {
+            ((InitializableDescriptor) setterDescriptor).addDependency(descriptor);
         } else {
             descriptor.finalizeInit();
         }
diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ValueParameterDescriptorImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ValueParameterDescriptorImpl.kt
index 4585625..bc21685 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ValueParameterDescriptorImpl.kt
+++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ValueParameterDescriptorImpl.kt
@@ -65,8 +65,8 @@
                     declaresDefaultValue, isCrossinline, isNoinline, varargElementType, source,
                     destructuringVariables
                 )
-            if (containingDeclaration is DeclarationDescriptorNonRootImpl) {
-                containingDeclaration.addInitFinalizationAction(valueParameterDescriptor::finalizeInit)
+            if (containingDeclaration is InitializableDescriptor) {
+                containingDeclaration.addDependency(valueParameterDescriptor)
             } else {
                 valueParameterDescriptor.finalizeInit()
             }
diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt
index eef1ea8..55b2a51 100644
--- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt
+++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt
@@ -7,7 +7,10 @@
 
 import org.jetbrains.kotlin.descriptors.*
 import org.jetbrains.kotlin.descriptors.annotations.Annotations
-import org.jetbrains.kotlin.descriptors.impl.*
+import org.jetbrains.kotlin.descriptors.impl.FieldDescriptorImpl
+import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
+import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
+import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
 import org.jetbrains.kotlin.metadata.ProtoBuf
 import org.jetbrains.kotlin.metadata.deserialization.*
 import org.jetbrains.kotlin.protobuf.MessageLite
@@ -341,8 +344,8 @@
                 proto.varargElementType(c.typeTable)?.let { c.typeDeserializer.type(it) },
                 SourceElement.NO_SOURCE
             )
-            if (callableDescriptor is DeclarationDescriptorNonRootImpl) {
-                callableDescriptor.addInitFinalizationAction(valueParameterDescriptor::finalizeInit)
+            if (callableDescriptor is InitializableDescriptor) {
+                callableDescriptor.addDependency(valueParameterDescriptor)
             } else {
                 valueParameterDescriptor.finalizeInit()
             }