Skip to content

Commit 8c5d40c

Browse files
committed
HEADER-COMPILATION: Implement returning nullexclexcl on each method body
1 parent 82287d3 commit 8c5d40c

File tree

1 file changed

+47
-12
lines changed

1 file changed

+47
-12
lines changed

compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.diagnostics.*
3333
import org.jetbrains.kotlin.fir.expressions.*
3434
import org.jetbrains.kotlin.fir.expressions.builder.*
3535
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
36+
import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock
3637
import org.jetbrains.kotlin.fir.lightTree.fir.*
3738
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.ModifierList
3839
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeParameterModifierList
@@ -53,6 +54,7 @@ import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
5354
import org.jetbrains.kotlin.lexer.KtTokens.*
5455
import org.jetbrains.kotlin.name.*
5556
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
57+
import org.jetbrains.kotlin.types.ConstantValueKind
5658
import org.jetbrains.kotlin.util.getChildren
5759
import org.jetbrains.kotlin.utils.addToStdlib.runIf
5860
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
@@ -1239,8 +1241,12 @@ class LightTreeRawFirDeclarationBuilder(
12391241
typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters)
12401242
valueParameters += firValueParameters.map { it.firValueParameter }
12411243
// TODO-HEADER-COMPILATION: Potentially remove this and produce an empty constructor body.
1242-
val (body, contractDescription) = withForcedLocalContext {
1243-
convertFunctionBody(block, null, allowLegacyContractDescription = true)
1244+
val (body, contractDescription) = if (headerCompilationMode) {
1245+
buildEmptyExpressionBlock() to null
1246+
} else {
1247+
withForcedLocalContext {
1248+
convertFunctionBody(block, null, allowLegacyContractDescription = true)
1249+
}
12441250
}
12451251
this.body = body
12461252
contractDescription?.let { this.contractDescription = it }
@@ -1761,8 +1767,12 @@ class LightTreeRawFirDeclarationBuilder(
17611767
}
17621768
val allowLegacyContractDescription = outerContractDescription == null
17631769
// TODO-HEADER-COMPILATION: Potentially remove getter/setter code.
1764-
val bodyWithContractDescription = withForcedLocalContext {
1765-
convertFunctionBody(block, expression, allowLegacyContractDescription)
1770+
val bodyWithContractDescription = if (headerCompilationMode) {
1771+
buildEmptyExpressionBlock() to null
1772+
} else {
1773+
withForcedLocalContext {
1774+
convertFunctionBody(block, expression, allowLegacyContractDescription)
1775+
}
17661776
}
17671777
this.body = bodyWithContractDescription.first
17681778
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
@@ -2066,8 +2076,39 @@ class LightTreeRawFirDeclarationBuilder(
20662076
}
20672077

20682078
val allowLegacyContractDescription = outerContractDescription == null
2069-
val bodyWithContractDescription = withForcedLocalContext {
2070-
convertFunctionBody(block, expression, allowLegacyContractDescription)
2079+
2080+
// TODO: HEADER-COMPILATION
2081+
// replacing method bodies with `return null!!` doesn't seem to be ideal since it's producing a rather
2082+
// long bytecode sequence:
2083+
// Code:
2084+
// 0: aconst_null
2085+
// 1: dup
2086+
// 2: invokestatic #18 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
2087+
// 5: pop
2088+
// 6: new #26 // class kotlin/KotlinNothingValueException
2089+
// 9: dup
2090+
// 10: invokespecial #27 // Method kotlin/KotlinNothingValueException."<init>":()V
2091+
// 13: athrow
2092+
//
2093+
// Consider unconditionally throwing an exception instead.
2094+
fun buildReturnNullExclExclBlock() = (
2095+
FirSingleExpressionBlock(
2096+
buildReturnExpression {
2097+
this.target = target
2098+
result = buildCheckNotNullCall {
2099+
argumentList = buildUnaryArgumentList(
2100+
buildLiteralExpression(null, ConstantValueKind.Null, null, setType = true)
2101+
)
2102+
}
2103+
}
2104+
) to null)
2105+
2106+
val bodyWithContractDescription = if (headerCompilationMode) {
2107+
buildReturnNullExclExclBlock()
2108+
} else {
2109+
withForcedLocalContext {
2110+
convertFunctionBody(block, expression, allowLegacyContractDescription)
2111+
}
20712112
}
20722113
this.body = bodyWithContractDescription.first
20732114
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
@@ -2106,10 +2147,6 @@ class LightTreeRawFirDeclarationBuilder(
21062147
expression: LighterASTNode?,
21072148
allowLegacyContractDescription: Boolean
21082149
): Pair<FirBlock?, FirContractDescription?> {
2109-
// TODO-HEADER-COMPILATION: Another option to produce empty methods
2110-
// TODO-HEADER-COMPILATION: is to make this function return nothing.
2111-
if (headerCompilationMode)
2112-
return null to null
21132150
return when {
21142151
blockNode != null -> {
21152152
val block = convertBlock(blockNode)
@@ -2145,8 +2182,6 @@ class LightTreeRawFirDeclarationBuilder(
21452182
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseBlock
21462183
*/
21472184
fun convertBlock(block: LighterASTNode?): FirBlock {
2148-
// TODO-HEADER-COMPILATION: One option is to prevent the frontend
2149-
// TODO-HEADER-COMPILATION: from producing IR here.
21502185
if (block == null) return buildEmptyExpressionBlock()
21512186
if (block.tokenType != BLOCK) {
21522187
return FirSingleExpressionBlock(

0 commit comments

Comments
 (0)