From 8f45acd71d88423842b0cf24e0da871a8d615051 Mon Sep 17 00:00:00 2001 From: pyos Date: Thu, 19 Jan 2023 14:08:45 +0100 Subject: [PATCH] FIR: remove deadness-related hacks from FirMemberPropertiesChecker Pretty sure the changes I've made to class graph construction should've made it so that deadness is propagated through to each member's graph correctly. --- .../declaration/FirMemberPropertiesChecker.kt | 33 +++---------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt index 280fd788d44..b1b58383ece 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfo import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfoCollector import org.jetbrains.kotlin.fir.analysis.checkers.contains @@ -29,15 +28,17 @@ import org.jetbrains.kotlin.lexer.KtTokens object FirMemberPropertiesChecker : FirClassChecker() { override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { val info = declaration.collectInitializationInfo() - val deadEnds = declaration.collectDeadEndDeclarations() - var reachedDeadEnd = false + var reachedDeadEnd = + (declaration as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph?.enterNode?.isDead == true for (innerDeclaration in declaration.declarations) { if (innerDeclaration is FirProperty) { val symbol = innerDeclaration.symbol val isInitialized = innerDeclaration.initializer != null || info?.get(symbol)?.isDefinitelyVisited() == true checkProperty(declaration, innerDeclaration, isInitialized, context, reporter, !reachedDeadEnd) } - reachedDeadEnd = reachedDeadEnd || deadEnds.contains(innerDeclaration) + // Can't just look at each property's graph's enterNode because they may have no graph if there is no initializer. + reachedDeadEnd = reachedDeadEnd || + (innerDeclaration as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph?.exitNode?.isDead == true } } @@ -122,28 +123,4 @@ object FirMemberPropertiesChecker : FirClassChecker() { } } } - - private fun FirClass.collectDeadEndDeclarations(): Set { - val controlFlowGraphReference = when (this) { - is FirAnonymousObject -> this.controlFlowGraphReference - is FirRegularClass -> this.controlFlowGraphReference - else -> null - } - val cfg = controlFlowGraphReference?.controlFlowGraph ?: return emptySet() - return cfg.exitNode.previousNodes - .map { it.fir } - .filter { it.isDeadEnd() } - .toSet() - } - - /** - * The idea is to find presumably exit node is dead one - * 1. in the case of block expression, it is BlockExitNode - * 2. in other cases treat any dead node that leads to exitNode as evidence of deadness - * This is all a workaround because ideally exit node itself should be dead if it is unreachable - */ - private fun FirElement.isDeadEnd(): Boolean { - val cfg = (this as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph ?: return false - return cfg.exitNode.previousNodes.find { it is BlockExitNode }?.isDead ?: cfg.exitNode.previousNodes.any { it.isDead } - } }