FIR: Rework FirRegularTowerDataContexts
- Get rid of SPECIAL mode (just left REGULAR and class-related instead) - Clear naming - Restore contexts after lambda/callable reference are processed The test has been failing before this change because after callable reference is resolved, its tower data context has been left erroneously in the SPECIAL-related entry
This commit is contained in:
+6
@@ -7164,6 +7164,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
runTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartCastWithLambdaAndCallableReference.kt")
|
||||||
|
public void testSmartCastWithLambdaAndCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataFlow/smartCastWithLambdaAndCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("WhenSubject.kt")
|
@TestMetadata("WhenSubject.kt")
|
||||||
public void testWhenSubject() throws Exception {
|
public void testWhenSubject() throws Exception {
|
||||||
|
|||||||
+6
@@ -7164,6 +7164,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
runTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartCastWithLambdaAndCallableReference.kt")
|
||||||
|
public void testSmartCastWithLambdaAndCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataFlow/smartCastWithLambdaAndCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("WhenSubject.kt")
|
@TestMetadata("WhenSubject.kt")
|
||||||
public void testWhenSubject() throws Exception {
|
public void testWhenSubject() throws Exception {
|
||||||
|
|||||||
+6
@@ -7164,6 +7164,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
runTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartCastWithLambdaAndCallableReference.kt")
|
||||||
|
public void testSmartCastWithLambdaAndCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataFlow/smartCastWithLambdaAndCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("WhenSubject.kt")
|
@TestMetadata("WhenSubject.kt")
|
||||||
public void testWhenSubject() throws Exception {
|
public void testWhenSubject() throws Exception {
|
||||||
|
|||||||
+19
-20
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
enum class FirTowerDataMode {
|
enum class FirTowerDataMode {
|
||||||
MEMBER_DECLARATION,
|
REGULAR,
|
||||||
NESTED_CLASS,
|
NESTED_CLASS,
|
||||||
COMPANION_OBJECT,
|
COMPANION_OBJECT,
|
||||||
CONSTRUCTOR_HEADER,
|
CONSTRUCTOR_HEADER,
|
||||||
@@ -22,65 +22,64 @@ class FirRegularTowerDataContexts private constructor(
|
|||||||
private val modeMap: EnumMap<FirTowerDataMode, FirTowerDataContext>,
|
private val modeMap: EnumMap<FirTowerDataMode, FirTowerDataContext>,
|
||||||
val primaryConstructorPureParametersScope: FirLocalScope?,
|
val primaryConstructorPureParametersScope: FirLocalScope?,
|
||||||
val primaryConstructorAllParametersScope: FirLocalScope?,
|
val primaryConstructorAllParametersScope: FirLocalScope?,
|
||||||
val mode: FirTowerDataMode,
|
val activeMode: FirTowerDataMode,
|
||||||
) {
|
) {
|
||||||
constructor(
|
constructor(
|
||||||
forMemberDeclarations: FirTowerDataContext,
|
regular: FirTowerDataContext,
|
||||||
forNestedClasses: FirTowerDataContext? = null,
|
forNestedClasses: FirTowerDataContext? = null,
|
||||||
forCompanionObject: FirTowerDataContext? = null,
|
forCompanionObject: FirTowerDataContext? = null,
|
||||||
forConstructorHeaders: FirTowerDataContext? = null,
|
forConstructorHeaders: FirTowerDataContext? = null,
|
||||||
forEnumEntries: FirTowerDataContext? = null,
|
forEnumEntries: FirTowerDataContext? = null,
|
||||||
forSpecial: FirTowerDataContext? = null,
|
|
||||||
primaryConstructorPureParametersScope: FirLocalScope? = null,
|
primaryConstructorPureParametersScope: FirLocalScope? = null,
|
||||||
primaryConstructorAllParametersScope: FirLocalScope? = null,
|
primaryConstructorAllParametersScope: FirLocalScope? = null,
|
||||||
) : this(
|
) : this(
|
||||||
enumMap(forMemberDeclarations, forNestedClasses, forCompanionObject, forConstructorHeaders, forEnumEntries, forSpecial),
|
enumMap(regular, forNestedClasses, forCompanionObject, forConstructorHeaders, forEnumEntries),
|
||||||
primaryConstructorPureParametersScope,
|
primaryConstructorPureParametersScope,
|
||||||
primaryConstructorAllParametersScope,
|
primaryConstructorAllParametersScope,
|
||||||
FirTowerDataMode.MEMBER_DECLARATION
|
FirTowerDataMode.REGULAR
|
||||||
)
|
)
|
||||||
|
|
||||||
val currentContext: FirTowerDataContext?
|
val currentContext: FirTowerDataContext?
|
||||||
get() = modeMap[mode]
|
get() = modeMap[activeMode]
|
||||||
|
|
||||||
fun copy(newContext: FirTowerDataContext): FirRegularTowerDataContexts {
|
fun replaceCurrentlyActiveContext(newContext: FirTowerDataContext): FirRegularTowerDataContexts {
|
||||||
val modeMap = EnumMap<FirTowerDataMode, FirTowerDataContext>(FirTowerDataMode::class.java)
|
val modeMap = EnumMap<FirTowerDataMode, FirTowerDataContext>(FirTowerDataMode::class.java)
|
||||||
modeMap.putAll(this.modeMap)
|
modeMap.putAll(this.modeMap)
|
||||||
modeMap[mode] = newContext
|
modeMap[activeMode] = newContext
|
||||||
return FirRegularTowerDataContexts(modeMap, primaryConstructorPureParametersScope, primaryConstructorAllParametersScope, mode)
|
return FirRegularTowerDataContexts(modeMap, primaryConstructorPureParametersScope, primaryConstructorAllParametersScope, activeMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copy(newMode: FirTowerDataMode): FirRegularTowerDataContexts {
|
fun replaceTowerDataMode(newMode: FirTowerDataMode): FirRegularTowerDataContexts {
|
||||||
if (newMode == mode) return this
|
if (newMode == activeMode) return this
|
||||||
return FirRegularTowerDataContexts(modeMap, primaryConstructorPureParametersScope, primaryConstructorAllParametersScope, newMode)
|
return FirRegularTowerDataContexts(modeMap, primaryConstructorPureParametersScope, primaryConstructorAllParametersScope, newMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyWithSpecial(newContext: FirTowerDataContext): FirRegularTowerDataContexts {
|
// Effectively equal to replaceTowerDataMode(REGULAR) + replaceCurrentlyActiveContext(newContext)
|
||||||
|
// But left just for sake of optimization
|
||||||
|
fun replaceAndSetActiveRegularContext(newContext: FirTowerDataContext): FirRegularTowerDataContexts {
|
||||||
val modeMap = EnumMap<FirTowerDataMode, FirTowerDataContext>(FirTowerDataMode::class.java)
|
val modeMap = EnumMap<FirTowerDataMode, FirTowerDataContext>(FirTowerDataMode::class.java)
|
||||||
modeMap.putAll(this.modeMap)
|
modeMap.putAll(this.modeMap)
|
||||||
modeMap[FirTowerDataMode.SPECIAL] = newContext
|
modeMap[FirTowerDataMode.REGULAR] = newContext
|
||||||
return FirRegularTowerDataContexts(
|
return FirRegularTowerDataContexts(
|
||||||
modeMap, primaryConstructorPureParametersScope, primaryConstructorAllParametersScope, FirTowerDataMode.SPECIAL
|
modeMap, primaryConstructorPureParametersScope, primaryConstructorAllParametersScope, FirTowerDataMode.REGULAR
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun enumMap(
|
private fun enumMap(
|
||||||
forMemberDeclarations: FirTowerDataContext,
|
regular: FirTowerDataContext,
|
||||||
forNestedClasses: FirTowerDataContext?,
|
forNestedClasses: FirTowerDataContext?,
|
||||||
forCompanionObject: FirTowerDataContext?,
|
forCompanionObject: FirTowerDataContext?,
|
||||||
forConstructorHeaders: FirTowerDataContext?,
|
forConstructorHeaders: FirTowerDataContext?,
|
||||||
forEnumEntries: FirTowerDataContext?,
|
forEnumEntries: FirTowerDataContext?,
|
||||||
forSpecial: FirTowerDataContext?,
|
|
||||||
): EnumMap<FirTowerDataMode, FirTowerDataContext> {
|
): EnumMap<FirTowerDataMode, FirTowerDataContext> {
|
||||||
val modeMap = EnumMap<FirTowerDataMode, FirTowerDataContext>(FirTowerDataMode::class.java)
|
val modeMap = EnumMap<FirTowerDataMode, FirTowerDataContext>(FirTowerDataMode::class.java)
|
||||||
modeMap[FirTowerDataMode.MEMBER_DECLARATION] = forMemberDeclarations
|
modeMap[FirTowerDataMode.REGULAR] = regular
|
||||||
modeMap[FirTowerDataMode.NESTED_CLASS] = forNestedClasses
|
modeMap[FirTowerDataMode.NESTED_CLASS] = forNestedClasses
|
||||||
modeMap[FirTowerDataMode.COMPANION_OBJECT] = forCompanionObject
|
modeMap[FirTowerDataMode.COMPANION_OBJECT] = forCompanionObject
|
||||||
modeMap[FirTowerDataMode.CONSTRUCTOR_HEADER] = forConstructorHeaders
|
modeMap[FirTowerDataMode.CONSTRUCTOR_HEADER] = forConstructorHeaders
|
||||||
modeMap[FirTowerDataMode.ENUM_ENTRY] = forEnumEntries
|
modeMap[FirTowerDataMode.ENUM_ENTRY] = forEnumEntries
|
||||||
modeMap[FirTowerDataMode.SPECIAL] = forSpecial
|
|
||||||
return modeMap
|
return modeMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-24
@@ -52,7 +52,7 @@ class BodyResolveContext(
|
|||||||
lateinit var file: FirFile
|
lateinit var file: FirFile
|
||||||
|
|
||||||
@PrivateForInline
|
@PrivateForInline
|
||||||
var regularTowerDataContexts = FirRegularTowerDataContexts(forMemberDeclarations = FirTowerDataContext())
|
var regularTowerDataContexts = FirRegularTowerDataContexts(regular = FirTowerDataContext())
|
||||||
|
|
||||||
@PrivateForInline
|
@PrivateForInline
|
||||||
val specialTowerDataContexts = FirSpecialTowerDataContexts()
|
val specialTowerDataContexts = FirSpecialTowerDataContexts()
|
||||||
@@ -64,9 +64,9 @@ class BodyResolveContext(
|
|||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
var towerDataMode: FirTowerDataMode
|
var towerDataMode: FirTowerDataMode
|
||||||
get() = regularTowerDataContexts.mode
|
get() = regularTowerDataContexts.activeMode
|
||||||
set(value) {
|
set(value) {
|
||||||
regularTowerDataContexts = regularTowerDataContexts.copy(newMode = value)
|
regularTowerDataContexts = regularTowerDataContexts.replaceTowerDataMode(newMode = value)
|
||||||
}
|
}
|
||||||
|
|
||||||
val implicitReceiverStack: ImplicitReceiverStack
|
val implicitReceiverStack: ImplicitReceiverStack
|
||||||
@@ -95,7 +95,7 @@ class BodyResolveContext(
|
|||||||
get() = containingClassDeclarations.lastOrNull()
|
get() = containingClassDeclarations.lastOrNull()
|
||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
inline fun <T> withNewTowerDataForClass(newContexts: FirRegularTowerDataContexts, f: () -> T): T {
|
inline fun <T> withTowerDataContexts(newContexts: FirRegularTowerDataContexts, f: () -> T): T {
|
||||||
val old = regularTowerDataContexts
|
val old = regularTowerDataContexts
|
||||||
regularTowerDataContexts = newContexts
|
regularTowerDataContexts = newContexts
|
||||||
return try {
|
return try {
|
||||||
@@ -158,14 +158,14 @@ class BodyResolveContext(
|
|||||||
|
|
||||||
@PrivateForInline
|
@PrivateForInline
|
||||||
inline fun <T> withTowerDataMode(mode: FirTowerDataMode, f: () -> T): T {
|
inline fun <T> withTowerDataMode(mode: FirTowerDataMode, f: () -> T): T {
|
||||||
return withTowerModeCleanup {
|
return withTowerDataModeCleanup {
|
||||||
towerDataMode = mode
|
towerDataMode = mode
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PrivateForInline
|
@PrivateForInline
|
||||||
inline fun <R> withTowerModeCleanup(l: () -> R): R {
|
inline fun <R> withTowerDataModeCleanup(l: () -> R): R {
|
||||||
val initialMode = towerDataMode
|
val initialMode = towerDataMode
|
||||||
return try {
|
return try {
|
||||||
l()
|
l()
|
||||||
@@ -176,7 +176,7 @@ class BodyResolveContext(
|
|||||||
|
|
||||||
@PrivateForInline
|
@PrivateForInline
|
||||||
fun replaceTowerDataContext(newContext: FirTowerDataContext) {
|
fun replaceTowerDataContext(newContext: FirTowerDataContext) {
|
||||||
regularTowerDataContexts = regularTowerDataContexts.copy(newContext)
|
regularTowerDataContexts = regularTowerDataContexts.replaceCurrentlyActiveContext(newContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@PrivateForInline
|
@PrivateForInline
|
||||||
@@ -315,23 +315,19 @@ class BodyResolveContext(
|
|||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
inline fun <T> withAnonymousFunctionTowerDataContext(symbol: FirAnonymousFunctionSymbol, f: () -> T): T {
|
inline fun <T> withAnonymousFunctionTowerDataContext(symbol: FirAnonymousFunctionSymbol, f: () -> T): T {
|
||||||
return withTowerModeCleanup {
|
return withTemporaryRegularContext(specialTowerDataContexts.getAnonymousFunctionContext(symbol), f)
|
||||||
val newContext = specialTowerDataContexts.getAnonymousFunctionContext(symbol)
|
|
||||||
if (newContext != null) {
|
|
||||||
regularTowerDataContexts = regularTowerDataContexts.copyWithSpecial(newContext)
|
|
||||||
}
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
inline fun <T> withCallableReferenceTowerDataContext(access: FirCallableReferenceAccess, f: () -> T): T {
|
inline fun <T> withCallableReferenceTowerDataContext(access: FirCallableReferenceAccess, f: () -> T): T {
|
||||||
return withTowerModeCleanup {
|
return withTemporaryRegularContext(specialTowerDataContexts.getCallableReferenceContext(access), f)
|
||||||
val newContext = specialTowerDataContexts.getCallableReferenceContext(access)
|
}
|
||||||
if (newContext != null) {
|
|
||||||
regularTowerDataContexts = regularTowerDataContexts.copyWithSpecial(newContext)
|
@PrivateForInline
|
||||||
}
|
inline fun <T> withTemporaryRegularContext(newContext: FirTowerDataContext?, f: () -> T): T {
|
||||||
f()
|
if (newContext == null) return f()
|
||||||
|
return withTowerDataModeCleanup {
|
||||||
|
withTowerDataContexts(regularTowerDataContexts.replaceAndSetActiveRegularContext(newContext), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,7 +392,7 @@ class BodyResolveContext(
|
|||||||
withContainerClass(regularClass, f)
|
withContainerClass(regularClass, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return withTowerModeCleanup {
|
return withTowerDataModeCleanup {
|
||||||
if (!regularClass.isInner && containerIfAny is FirRegularClass) {
|
if (!regularClass.isInner && containerIfAny is FirRegularClass) {
|
||||||
towerDataMode = if (regularClass.isCompanion) {
|
towerDataMode = if (regularClass.isCompanion) {
|
||||||
FirTowerDataMode.COMPANION_OBJECT
|
FirTowerDataMode.COMPANION_OBJECT
|
||||||
@@ -486,12 +482,11 @@ class BodyResolveContext(
|
|||||||
statics,
|
statics,
|
||||||
scopeForConstructorHeader,
|
scopeForConstructorHeader,
|
||||||
scopeForEnumEntries,
|
scopeForEnumEntries,
|
||||||
forSpecial = null,
|
|
||||||
primaryConstructorPureParametersScope,
|
primaryConstructorPureParametersScope,
|
||||||
primaryConstructorAllParametersScope
|
primaryConstructorAllParametersScope
|
||||||
)
|
)
|
||||||
|
|
||||||
return withNewTowerDataForClass(newContexts) {
|
return withTowerDataContexts(newContexts) {
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -521,7 +516,7 @@ class BodyResolveContext(
|
|||||||
val whenSubjectImportingScope = whenSubjectImportingScopes.lastOrNull() ?: return f()
|
val whenSubjectImportingScope = whenSubjectImportingScopes.lastOrNull() ?: return f()
|
||||||
val newTowerDataContext = towerDataContext.addNonLocalScope(whenSubjectImportingScope)
|
val newTowerDataContext = towerDataContext.addNonLocalScope(whenSubjectImportingScope)
|
||||||
val newContexts = FirRegularTowerDataContexts(newTowerDataContext)
|
val newContexts = FirRegularTowerDataContexts(newTowerDataContext)
|
||||||
return withNewTowerDataForClass(newContexts) {
|
return withTowerDataContexts(newContexts) {
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// SKIP_TXT
|
||||||
|
|
||||||
|
fun <T> T.myApply(block: T.() -> Unit): T = this
|
||||||
|
|
||||||
|
fun bar(): Int = 1
|
||||||
|
|
||||||
|
interface A : C
|
||||||
|
interface B : C
|
||||||
|
interface C {
|
||||||
|
fun baz()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.foo() = myApply {
|
||||||
|
when (this) {
|
||||||
|
is A -> ::bar
|
||||||
|
is B -> ::bar
|
||||||
|
else -> throw RuntimeException()
|
||||||
|
}
|
||||||
|
|
||||||
|
baz() // Smart cast should work
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// SKIP_TXT
|
||||||
|
|
||||||
|
fun <T> T.myApply(block: T.() -> Unit): T = this
|
||||||
|
|
||||||
|
fun bar(): Int = 1
|
||||||
|
|
||||||
|
interface A : C
|
||||||
|
interface B : C
|
||||||
|
interface C {
|
||||||
|
fun baz()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.foo() = myApply {
|
||||||
|
when (this) {
|
||||||
|
is A -> ::bar
|
||||||
|
is B -> ::bar
|
||||||
|
else -> throw RuntimeException()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!UNRESOLVED_REFERENCE!>baz<!>() // Smart cast should work
|
||||||
|
}
|
||||||
Generated
+6
@@ -7170,6 +7170,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
runTest("compiler/testData/diagnostics/tests/dataFlow/IsExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartCastWithLambdaAndCallableReference.kt")
|
||||||
|
public void testSmartCastWithLambdaAndCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataFlow/smartCastWithLambdaAndCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("WhenSubject.kt")
|
@TestMetadata("WhenSubject.kt")
|
||||||
public void testWhenSubject() throws Exception {
|
public void testWhenSubject() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user