From 97a12af03eeb911cf1864834a8a53084730c8923 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Wed, 12 Jul 2023 14:27:33 +0200 Subject: [PATCH] [FIR] fix publication race in fakeOverrideSubstitution Problem: fakeOverrideSubstitution was set to null before the return type was published, so another thread can see a state where fakeOverrideSubstitution is null and a return type is implicit simultaneously ^KT-60385 ^KT-59758 Fixed --- .../kotlin/fir/scopes/FakeOverrideTypeCalculator.kt | 8 +++++--- .../body/resolve/FirImplicitBodyResolve.kt | 11 +++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt index 25ec9a468b6..5e22f7a5e7c 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt @@ -26,19 +26,21 @@ abstract class FakeOverrideTypeCalculator { abstract class AbstractFakeOverrideTypeCalculator : FakeOverrideTypeCalculator() { override fun computeReturnType(declaration: FirCallableDeclaration): FirResolvedTypeRef? { - val fakeOverrideSubstitution = declaration.attributes.fakeOverrideSubstitution - ?: return declaration.getResolvedTypeRef() + val fakeOverrideSubstitution = declaration.attributes.fakeOverrideSubstitution ?: return declaration.getResolvedTypeRef() + + // TODO: drop synchronized in KT-60385 synchronized(fakeOverrideSubstitution) { if (declaration.attributes.fakeOverrideSubstitution == null) { return declaration.returnTypeRef as FirResolvedTypeRef } + val (substitutor, baseSymbol) = fakeOverrideSubstitution val baseDeclaration = baseSymbol.fir as FirCallableDeclaration val baseReturnType = computeReturnType(baseDeclaration)?.type ?: return null - declaration.attributes.fakeOverrideSubstitution = null val coneType = substitutor.substituteOrSelf(baseReturnType) val returnType = declaration.returnTypeRef.resolvedTypeFromPrototype(coneType) declaration.replaceReturnTypeRef(returnType) + declaration.attributes.fakeOverrideSubstitution = null return returnType } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt index fe9a26d9eb6..c212e1038df 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.visitors.FirTransformer @@ -231,9 +232,13 @@ open class ReturnTypeCalculatorWithJump( if (declaration.isSubstitutionOrIntersectionOverride) { val fakeOverrideSubstitution = declaration.attributes.fakeOverrideSubstitution ?: return declaration.returnTypeRef as FirResolvedTypeRef + + // TODO: drop synchronized in KT-60385 synchronized(fakeOverrideSubstitution) { - (declaration.returnTypeRef as? FirResolvedTypeRef)?.let { return it } - declaration.attributes.fakeOverrideSubstitution = null + if (declaration.attributes.fakeOverrideSubstitution == null) { + return declaration.returnTypeRef as FirResolvedTypeRef + } + val (substitutor, baseSymbol) = fakeOverrideSubstitution val baseDeclaration = baseSymbol.fir as FirCallableDeclaration val baseReturnTypeRef = tryCalculateReturnType(baseDeclaration) @@ -245,6 +250,8 @@ open class ReturnTypeCalculatorWithJump( declaration.getter?.replaceReturnTypeRef(returnType) declaration.setter?.valueParameters?.firstOrNull()?.replaceReturnTypeRef(returnType) } + + declaration.attributes.fakeOverrideSubstitution = null return returnType } }