FIR: enhance (using mode inside) BodyResolveContext.withAnonymousFunction

This commit is contained in:
Mikhail Glukhikh
2021-03-10 14:24:34 +03:00
parent 798d848a91
commit 2db413d535
2 changed files with 37 additions and 47 deletions
@@ -214,10 +214,6 @@ class BodyResolveContext(
updateLastScope { storeBackingField(property) } updateLastScope { storeBackingField(property) }
} }
fun saveContextForAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
towerDataContextForAnonymousFunctions[anonymousFunction.symbol] = towerDataContext
}
fun dropContextForAnonymousFunction(anonymousFunction: FirAnonymousFunction) { fun dropContextForAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
towerDataContextForAnonymousFunctions.remove(anonymousFunction.symbol) towerDataContextForAnonymousFunctions.remove(anonymousFunction.symbol)
} }
@@ -404,16 +400,22 @@ class BodyResolveContext(
inline fun <T> withAnonymousFunction( inline fun <T> withAnonymousFunction(
anonymousFunction: FirAnonymousFunction, anonymousFunction: FirAnonymousFunction,
holder: SessionHolder, holder: SessionHolder,
isInDependentContext: Boolean = false, mode: ResolutionMode,
crossinline f: () -> T crossinline f: () -> T
): T { ): T {
if (mode !is ResolutionMode.LambdaResolution) {
towerDataContextForAnonymousFunctions[anonymousFunction.symbol] = towerDataContext
}
if (mode is ResolutionMode.ContextDependent || mode is ResolutionMode.ContextDependentDelegate) {
return f()
}
return withTowerDataCleanup { return withTowerDataCleanup {
addLocalScope(FirLocalScope()) addLocalScope(FirLocalScope())
val receiverTypeRef = anonymousFunction.receiverTypeRef val receiverTypeRef = anonymousFunction.receiverTypeRef
val labelName = anonymousFunction.label?.name?.let { Name.identifier(it) } val labelName = anonymousFunction.label?.name?.let { Name.identifier(it) }
withContainer(anonymousFunction) { withContainer(anonymousFunction) {
withLabelAndReceiverType(labelName, anonymousFunction, receiverTypeRef?.coneType, holder) { withLabelAndReceiverType(labelName, anonymousFunction, receiverTypeRef?.coneType, holder) {
if (isInDependentContext) { if (mode is ResolutionMode.LambdaResolution) {
withLambdaBeingAnalyzedInDependentContext(anonymousFunction.symbol, f) withLambdaBeingAnalyzedInDependentContext(anonymousFunction.symbol, f)
} else { } else {
f() f()
@@ -104,14 +104,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
} }
} }
protected inline fun <T> withTypeParametersOf(declaration: FirMemberDeclaration, crossinline l: () -> T): T {
val scope = createTypeParameterScope(declaration)
return context.withTowerDataCleanup {
scope?.let { context.addNonLocalTowerDataElement(it.asTowerDataElement(isLocal = false)) }
l()
}
}
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): CompositeTransformResult<FirDeclaration> { override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): CompositeTransformResult<FirDeclaration> {
if (enumEntry.resolvePhase == transformerPhase) return enumEntry.compose() if (enumEntry.resolvePhase == transformerPhase) return enumEntry.compose()
transformer.replaceDeclarationResolvePhaseIfNeeded(enumEntry, transformerPhase) transformer.replaceDeclarationResolvePhaseIfNeeded(enumEntry, transformerPhase)
@@ -424,38 +416,31 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
private fun transformAnonymousFunctionWithLambdaResolution( private fun transformAnonymousFunctionWithLambdaResolution(
anonymousFunction: FirAnonymousFunction, lambdaResolution: ResolutionMode.LambdaResolution anonymousFunction: FirAnonymousFunction, lambdaResolution: ResolutionMode.LambdaResolution
): FirAnonymousFunction { ): FirAnonymousFunction {
fun transform(): FirAnonymousFunction { val expectedReturnType =
val expectedReturnType = lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef }
lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef } val result = transformFunction(anonymousFunction, withExpectedType(expectedReturnType)).single as FirAnonymousFunction
val body = result.body
if (result.returnTypeRef is FirImplicitTypeRef && body != null) {
// TODO: This part seems unnecessary because for lambdas in dependent context will be completed and their type
// should be replaced there properly
val returnType =
dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(result)
.firstNotNullResult { (it as? FirExpression)?.resultType?.coneTypeSafe() }
val result = transformFunction(anonymousFunction, withExpectedType(expectedReturnType)).single as FirAnonymousFunction if (returnType != null) {
result.transformReturnTypeRef(transformer, withExpectedType(returnType))
val body = result.body } else {
if (result.returnTypeRef is FirImplicitTypeRef && body != null) { result.transformReturnTypeRef(
// TODO: This part seems unnecessary because for lambdas in dependent context will be completed and their type transformer,
// should be replaced there properly withExpectedType(buildErrorTypeRef {
val returnType = diagnostic =
dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(result) ConeSimpleDiagnostic("Unresolved lambda return type", DiagnosticKind.InferenceError)
.firstNotNullResult { (it as? FirExpression)?.resultType?.coneTypeSafe() } })
)
if (returnType != null) {
result.transformReturnTypeRef(transformer, withExpectedType(returnType))
} else {
result.transformReturnTypeRef(
transformer,
withExpectedType(buildErrorTypeRef {
diagnostic =
ConeSimpleDiagnostic("Unresolved lambda return type", DiagnosticKind.InferenceError)
})
)
}
} }
return result
} }
return context.withAnonymousFunction(anonymousFunction, components, isInDependentContext = true) { return result
transform()
}
} }
override fun transformSimpleFunction( override fun transformSimpleFunction(
@@ -630,15 +615,18 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
anonymousFunction.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent) anonymousFunction.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent)
anonymousFunction.transformReceiverTypeRef(transformer, ResolutionMode.ContextIndependent) anonymousFunction.transformReceiverTypeRef(transformer, ResolutionMode.ContextIndependent)
anonymousFunction.valueParameters.forEach { it.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent) } anonymousFunction.valueParameters.forEach { it.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent) }
context.saveContextForAnonymousFunction(anonymousFunction)
} }
return when (data) { return when (data) {
is ResolutionMode.ContextDependent, is ResolutionMode.ContextDependentDelegate -> { is ResolutionMode.ContextDependent, is ResolutionMode.ContextDependentDelegate -> {
dataFlowAnalyzer.visitPostponedAnonymousFunction(anonymousFunction) context.withAnonymousFunction(anonymousFunction, components, data) {
anonymousFunction.addReturn().compose() dataFlowAnalyzer.visitPostponedAnonymousFunction(anonymousFunction)
anonymousFunction.addReturn().compose()
}
} }
is ResolutionMode.LambdaResolution -> { is ResolutionMode.LambdaResolution -> {
transformAnonymousFunctionWithLambdaResolution(anonymousFunction, data).addReturn().compose() context.withAnonymousFunction(anonymousFunction, components, data) {
transformAnonymousFunctionWithLambdaResolution(anonymousFunction, data).addReturn().compose()
}
} }
is ResolutionMode.WithExpectedType, is ResolutionMode.ContextIndependent -> { is ResolutionMode.WithExpectedType, is ResolutionMode.ContextIndependent -> {
val expectedTypeRef = (data as? ResolutionMode.WithExpectedType)?.expectedTypeRef ?: buildImplicitTypeRef() val expectedTypeRef = (data as? ResolutionMode.WithExpectedType)?.expectedTypeRef ?: buildImplicitTypeRef()
@@ -699,7 +687,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
) )
lambda = lambda.transformValueParameters(ImplicitToErrorTypeTransformer, null) lambda = lambda.transformValueParameters(ImplicitToErrorTypeTransformer, null)
val bodyExpectedType = returnTypeRefFromResolvedAtom ?: expectedTypeRef val bodyExpectedType = returnTypeRefFromResolvedAtom ?: expectedTypeRef
context.withAnonymousFunction(lambda, components) { context.withAnonymousFunction(lambda, components, data) {
lambda = transformFunction(lambda, withExpectedType(bodyExpectedType)).single as FirAnonymousFunction lambda = transformFunction(lambda, withExpectedType(bodyExpectedType)).single as FirAnonymousFunction
} }
// To separate function and separate commit // To separate function and separate commit