[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
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmentProvider
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
import org.jetbrains.kotlin.types.SubstitutingScopeProviderImpl
class CommonAnalysisParameters(
val metadataPartProviderFactory: (ModuleContent<*>) -> MetadataPartProvider
@@ -166,6 +167,7 @@ object CommonAnalyzerFacade : ResolverForModuleFactory() {
useInstance(declarationProviderFactory)
useImpl<MetadataPackageFragmentProvider>()
useImpl<ContractDeserializerImpl>()
useImpl<SubstitutingScopeProviderImpl>()
val metadataFinderFactory = ServiceManager.getService(moduleContext.project, MetadataFinderFactory::class.java)
?: error("No MetadataFinderFactory in project")
@@ -81,8 +81,7 @@ public class LocalVariableDescriptor extends VariableDescriptorWithInitializerIm
@NotNull
@Override
public LocalVariableDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
if (substitutor.isEmpty()) return this;
throw new UnsupportedOperationException(); // TODO
return this;
}
@Override
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitutio
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SubstitutingScopeProvider
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
@@ -77,7 +78,9 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
TypeConstructorSubstitution
.create(receiverType)
.wrapWithCapturingSubstitution(needApproximation = false)
.buildSubstitutor().let { callableDescriptor.substitute(it) } ?: return false
.buildSubstitutor().apply {
setSubstitutingScopeProvider(SubstitutingScopeProvider.DEFAULT)
}.let { callableDescriptor.substitute(it) } ?: return false
val nonApproximatedExpectedType = correspondingNotApproximatedTypeByDescriptor(substitutedDescriptor) ?: return false
if (!TypeUtils.contains(nonApproximatedExpectedType) { it.isCaptured() }) return false
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.types.SubstitutingScopeProviderImpl
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
@@ -103,6 +104,7 @@ fun createContainerForBodyResolve(
useImpl<AnnotationResolverImpl>()
useImpl<BodyResolver>()
useImpl<SubstitutingScopeProviderImpl>()
}
fun createContainerForLazyBodyResolve(
@@ -123,6 +125,7 @@ fun createContainerForLazyBodyResolve(
useImpl<AnnotationResolverImpl>()
useImpl<LazyTopDownAnalyzer>()
useImpl<BasicAbsentDescriptorHandler>()
useImpl<SubstitutingScopeProviderImpl>()
}
fun createContainerForLazyLocalClassifierAnalyzer(
@@ -154,6 +157,7 @@ fun createContainerForLazyLocalClassifierAnalyzer(
useImpl<LocalLazyDeclarationResolver>()
useInstance(languageVersionSettings)
useImpl<SubstitutingScopeProviderImpl>()
useInstance(statementFilter)
}
@@ -177,6 +181,7 @@ fun createContainerForLazyResolve(
useImpl<ResolveSession>()
useImpl<LazyTopDownAnalyzer>()
useImpl<SubstitutingScopeProviderImpl>()
}
fun createLazyResolveSession(moduleContext: ModuleContext, files: Collection<KtFile>): ResolveSession =
@@ -911,7 +911,8 @@ public class DescriptorResolver {
container instanceof ClassDescriptor && ((ClassDescriptor) container).isExpect(),
modifierList != null && PsiUtilsKt.hasActualModifier(modifierList),
modifierList != null && modifierList.hasModifier(KtTokens.EXTERNAL_KEYWORD),
propertyInfo.getHasDelegate()
propertyInfo.getHasDelegate(),
new SubstitutingScopeProviderImpl(languageVersionSettings)
);
List<TypeParameterDescriptorImpl> typeParameterDescriptors;
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.*
@@ -23,12 +25,13 @@ import org.jetbrains.kotlin.resolve.calls.components.AdditionalDiagnosticReporte
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
import org.jetbrains.kotlin.resolve.calls.inference.approximateCapturedTypes
import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.inference.substitute
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateCapturedTypes
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateIntegerLiteralTypes
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSafeReceiver
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
@@ -38,14 +41,13 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
@@ -293,15 +295,14 @@ class KotlinToResolvedCallTransformer(
// todo external argument
val argumentExpression = valueArgument.getArgumentExpression() ?: continue
updateRecordedType(argumentExpression, parameter, newContext, resolvedCall.isReallySuccess())
updateRecordedType(argumentExpression, parameter, newContext)
}
}
fun updateRecordedType(
expression: KtExpression,
parameter: ValueParameterDescriptor?,
context: BasicCallResolutionContext,
reportErrorForTypeMismatch: Boolean
context: BasicCallResolutionContext
): KotlinType? {
val deparenthesized = expression.let {
KtPsiUtil.getLastElementDeparenthesized(it, context.statementFilter)
@@ -318,9 +319,6 @@ class KotlinToResolvedCallTransformer(
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, deparenthesized) ?: updatedType
}
var reportErrorDuringTypeCheck = reportErrorForTypeMismatch
if (parameter != null && ImplicitIntegerCoercion.isEnabledForParameter(parameter)) {
val argumentCompileTimeValue = context.trace[BindingContext.COMPILE_TIME_VALUE, deparenthesized]
if (argumentCompileTimeValue != null && argumentCompileTimeValue.parameters.isConvertableConstVal) {
@@ -329,7 +327,6 @@ class KotlinToResolvedCallTransformer(
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(
context.trace, context.statementFilter, context.expectedType, generalNumberType, expression
)
reportErrorDuringTypeCheck = true
}
}
@@ -337,7 +334,7 @@ class KotlinToResolvedCallTransformer(
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context)
dataFlowAnalyzer.checkType(updatedType, deparenthesized, context, reportErrorDuringTypeCheck)
dataFlowAnalyzer.checkType(updatedType, deparenthesized, context, false)
return updatedType
}
@@ -690,32 +687,44 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
@Suppress("UNCHECKED_CAST")
resultingDescriptor = run {
val candidateDescriptor = resolvedCallAtom.candidateDescriptor
val containsCapturedTypes = resolvedCallAtom.candidateDescriptor.returnType?.contains { it is NewCapturedType } ?: false
val containsIntegerLiteralTypes = resolvedCallAtom.candidateDescriptor.returnType?.contains { it.constructor is IntegerLiteralTypeConstructor } ?: false
val containsIntegerLiteralTypes = resolvedCallAtom.candidateDescriptor.returnType?.contains {
it.constructor is IntegerLiteralTypeConstructor
} ?: false
when {
candidateDescriptor is FunctionDescriptor ||
(candidateDescriptor is PropertyDescriptor && (candidateDescriptor.typeParameters.isNotEmpty() || containsCapturedTypes || containsIntegerLiteralTypes)) ->
(candidateDescriptor is PropertyDescriptor && candidateDescriptor.typeParameters.isNotEmpty() || containsIntegerLiteralTypes) ->
// this code is very suspicious. Now it is very useful for BE, because they cannot do nothing with captured types,
// but it seems like temporary solution.
candidateDescriptor.substitute(resolvedCallAtom.substitutor).substituteAndApproximateCapturedTypes(
substitutor ?: FreshVariableNewTypeSubstitutor.Empty
)
candidateDescriptor.substituteAndApproximateIntegerLiteralTypes(resolvedCallAtom.substitutor).let {
if (substitutor != null) {
it.substitute(substitutor)
} else {
it
}
}
else ->
candidateDescriptor
}
} as D
typeArguments = resolvedCallAtom.substitutor.freshVariables.map {
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
TypeApproximator(substituted.constructor.builtIns)
.approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation)
?: substituted
(substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
}
calculateExpectedTypeForSamConvertedArgumentMap(substitutor)
}
fun approximateCapturedTypesAndHackSetters() {
val approximator = TypeApproximator(resultingDescriptor.builtIns)
resultingDescriptor = resultingDescriptor.hackSettersAccordingToCapturedOutTypes()
resultingDescriptor = resultingDescriptor.approximateCapturedTypes()
typeArguments = typeArguments.map {
approximator.approximateToSuperType(it, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) ?: it
}
}
fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
expedtedTypeForSamConvertedArgumentMap?.get(valueArgument)
@@ -808,3 +817,41 @@ fun NewResolvedCallImpl<*>.hasInferredReturnType(): Boolean {
val returnType = this.resultingDescriptor.returnType ?: return false
return !returnType.contains { ErrorUtils.isUninferredParameter(it) }
}
fun ResolvedCall<*>.approximateCapturedTypesAndHackSetters() {
when (this) {
is NewResolvedCallImpl<*> -> approximateCapturedTypesAndHackSetters()
is NewVariableAsFunctionResolvedCallImpl -> {
functionCall.approximateCapturedTypesAndHackSetters()
variableCall.approximateCapturedTypesAndHackSetters()
}
else -> throw UnsupportedOperationException("Illegal resolved call: $this")
}
}
fun <D : CallableDescriptor> D.hackSettersAccordingToCapturedOutTypes(): D {
return when (this) {
is PropertyDescriptorImpl -> hackSettersAccordingToCapturedOutTypes() as D
else -> this
}
}
private fun PropertyDescriptorImpl.hackSettersAccordingToCapturedOutTypes(): PropertyDescriptor {
val setter = setter ?: return this
val valueParameter = setter.valueParameters.first()
val inputType = valueParameter.type
val approximatedType = TypeApproximator(builtIns).approximateToSubType(
inputType.unwrap(),
TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation
) ?: return this
val newProperty = newCopyBuilder().build() as PropertyDescriptorImpl
val newSetter = with(setter) {
PropertySetterDescriptorImpl(newProperty, annotations, modality, visibility, isDefault, isExternal, isInline, kind, original, source)
}
newSetter.initialize(PropertySetterDescriptorImpl.createSetterParameter(newSetter, approximatedType, setter.annotations))
newProperty.initialize(getter, newSetter, backingField, delegateField)
newProperty.isSetterProjectedOut = true
return newProperty
}
@@ -382,6 +382,7 @@ class PSICallResolver(
return cache.getOrPut(implicitReceiver) {
context.transformToReceiverWithSmartCastInfo(implicitReceiver.value)
.prepareReceiverRegardingCaptureTypes()
}
}
}
@@ -110,6 +110,7 @@ class ResolvedAtomCompleter(
kotlinToResolvedCallTransformer.reportDiagnostics(topLevelCallContext, topLevelTrace, resolvedCall, diagnostics)
resolvedCall.approximateCapturedTypesAndHackSetters()
return resolvedCall
}
@@ -155,9 +156,7 @@ class ResolvedAtomCompleter(
.replaceBindingTrace(topLevelTrace)
val argumentExpression = resultValueArgument.valueArgument.getArgumentExpression() ?: continue
kotlinToResolvedCallTransformer.updateRecordedType(
argumentExpression, parameter = null, context = newContext, reportErrorForTypeMismatch = true
)
kotlinToResolvedCallTransformer.updateRecordedType(argumentExpression, parameter = null, context = newContext)
}
}
@@ -24,10 +24,12 @@ import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.SubstitutingScopeProvider
import org.jetbrains.kotlin.types.WrappedTypeFactory
interface LazyClassContext {
val declarationScopeProvider: DeclarationScopeProvider
val substitutingScopeProvider: SubstitutingScopeProvider
val storageManager: StorageManager
val trace: BindingTrace
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.storage.*;
import org.jetbrains.kotlin.types.SubstitutingScopeProvider;
import org.jetbrains.kotlin.types.WrappedTypeFactory;
import org.jetbrains.kotlin.utils.SmartList;
@@ -81,6 +82,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
private DelegationFilter delegationFilter;
private WrappedTypeFactory wrappedTypeFactory;
private PlatformDiagnosticSuppressor platformDiagnosticSuppressor;
private SubstitutingScopeProvider substitutingScopeProvider;
private final SyntheticResolveExtension syntheticResolveExtension;
@@ -146,6 +148,17 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
this.platformDiagnosticSuppressor = platformDiagnosticSuppressor;
}
@NotNull
@Override
public SubstitutingScopeProvider getSubstitutingScopeProvider() {
return substitutingScopeProvider;
}
@Inject
public void setSubstitutingScopeProvider(SubstitutingScopeProvider substitutingScopeProvider) {
this.substitutingScopeProvider = substitutingScopeProvider;
}
// Only calls from injectors expected
@Deprecated
public ResolveSession(
@@ -113,7 +113,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
) {
super(c.getStorageManager(), containingDeclaration, name,
KotlinSourceElementKt.toSourceElement(classLikeInfo.getCorrespondingClassOrObject()),
isExternal
isExternal, c.getSubstitutingScopeProvider()
);
this.c = c;
@@ -0,0 +1,49 @@
/*
* 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.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
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
class SubstitutingScopeProviderImpl(private val languageVersionSettings: LanguageVersionSettings) : SubstitutingScopeProvider {
override val isNewInferenceEnabled: Boolean get() = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
override fun createSubstitutingScope(workerScope: MemberScope, givenSubstitutor: TypeSubstitutor): SubstitutingScope {
return SubstitutingScope(workerScope, givenSubstitutor, this)
}
override fun provideApproximator(): CapturedTypeApproximator {
return if (isNewInferenceEnabled) {
NoCapturedTypeApproximator
} else {
OldCaptureTypeApproximator()
}
}
override fun provideCapturedTypeCreator(): CapturedTypeCreator {
return if (isNewInferenceEnabled) {
NoCapturedTypeCreator
} else {
OldCapturedTypeCreator
}
}
}
object NoCapturedTypeCreator : CapturedTypeCreator {
override fun createCapturedType(typeProjection: TypeProjection): TypeProjection {
return typeProjection
}
}
object NoCapturedTypeApproximator : CapturedTypeApproximator {
override fun approximateCapturedTypes(typeProjection: TypeProjection?, approximateContravariant: Boolean): TypeProjection? {
return typeProjection
}
}
@@ -958,6 +958,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
boolean result = true;
KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
KtExpression originalReportOn = reportOn;
if (reportOn instanceof KtQualifiedExpression) {
KtExpression selector = ((KtQualifiedExpression) reportOn).getSelectorExpression();
if (selector != null)
@@ -968,14 +969,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
if (propertyDescriptor.isSetterProjectedOut()) {
trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
trace.report(SETTER_PROJECTED_OUT.on(originalReportOn, propertyDescriptor));
result = false;
}
else if (setter != null) {
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expressionWithParenthesis, context.trace.getBindingContext());
assert resolvedCall != null
: "Call is not resolved for property setter: " + PsiUtilsKt.getElementTextWithContext(expressionWithParenthesis);
checkPropertySetterCall(context.replaceBindingTrace(trace), setter, resolvedCall, reportOn);
if (((PropertyDescriptor)resolvedCall.getResultingDescriptor()).isSetterProjectedOut()) {
trace.report(SETTER_PROJECTED_OUT.on(originalReportOn, propertyDescriptor));
result = false;
} else {
checkPropertySetterCall(context.replaceBindingTrace(trace), setter, resolvedCall, reportOn);
}
}
}
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.SubstitutingScopeProvider
import org.jetbrains.kotlin.types.WrappedTypeFactory
class LocalClassifierAnalyzer(
@@ -65,7 +66,8 @@ class LocalClassifierAnalyzer(
private val targetPlatformVersion: TargetPlatformVersion,
private val languageVersionSettings: LanguageVersionSettings,
private val delegationFilter: DelegationFilter,
private val wrappedTypeFactory: WrappedTypeFactory
private val wrappedTypeFactory: WrappedTypeFactory,
private val substitutingScopeProvider: SubstitutingScopeProvider
) {
fun processClassOrObject(
scope: LexicalWritableScope?,
@@ -99,7 +101,8 @@ class LocalClassifierAnalyzer(
languageVersionSettings,
SyntheticResolveExtension.getInstance(project),
delegationFilter,
wrappedTypeFactory
wrappedTypeFactory,
substitutingScopeProvider
)
)
@@ -126,7 +129,8 @@ class LocalClassDescriptorHolder(
val languageVersionSettings: LanguageVersionSettings,
val syntheticResolveExtension: SyntheticResolveExtension,
val delegationFilter: DelegationFilter,
val wrappedTypeFactory: WrappedTypeFactory
val wrappedTypeFactory: WrappedTypeFactory,
val substitutingScopeProvider: SubstitutingScopeProvider
) {
// We do not need to synchronize here, because this code is used strictly from one thread
private var classDescriptor: ClassDescriptor? = null
@@ -166,6 +170,7 @@ class LocalClassDescriptorHolder(
override val syntheticResolveExtension = this@LocalClassDescriptorHolder.syntheticResolveExtension
override val delegationFilter: DelegationFilter = this@LocalClassDescriptorHolder.delegationFilter
override val wrappedTypeFactory: WrappedTypeFactory = this@LocalClassDescriptorHolder.wrappedTypeFactory
override val substitutingScopeProvider: SubstitutingScopeProvider = this@LocalClassDescriptorHolder.substitutingScopeProvider
},
containingDeclaration,
classOrObject.nameAsSafeName,