Skip to content

Commit 2cd4178

Browse files
committed
HEADER-COMPILATION: Implement returning nullexclexcl on each method body
1 parent 54fc447 commit 2cd4178

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 }
@@ -1737,8 +1743,12 @@ class LightTreeRawFirDeclarationBuilder(
17371743
}
17381744
val allowLegacyContractDescription = outerContractDescription == null
17391745
// TODO-HEADER-COMPILATION: Potentially remove getter/setter code.
1740-
val bodyWithContractDescription = withForcedLocalContext {
1741-
convertFunctionBody(block, expression, allowLegacyContractDescription)
1746+
val bodyWithContractDescription = if (headerCompilationMode) {
1747+
buildEmptyExpressionBlock() to null
1748+
} else {
1749+
withForcedLocalContext {
1750+
convertFunctionBody(block, expression, allowLegacyContractDescription)
1751+
}
17421752
}
17431753
this.body = bodyWithContractDescription.first
17441754
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
@@ -2042,8 +2052,39 @@ class LightTreeRawFirDeclarationBuilder(
20422052
}
20432053

20442054
val allowLegacyContractDescription = outerContractDescription == null
2045-
val bodyWithContractDescription = withForcedLocalContext {
2046-
convertFunctionBody(block, expression, allowLegacyContractDescription)
2055+
2056+
// TODO: HEADER-COMPILATION
2057+
// replacing method bodies with `return null!!` doesn't seem to be ideal since it's producing a rather
2058+
// long bytecode sequence:
2059+
// Code:
2060+
// 0: aconst_null
2061+
// 1: dup
2062+
// 2: invokestatic #18 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
2063+
// 5: pop
2064+
// 6: new #26 // class kotlin/KotlinNothingValueException
2065+
// 9: dup
2066+
// 10: invokespecial #27 // Method kotlin/KotlinNothingValueException."<init>":()V
2067+
// 13: athrow
2068+
//
2069+
// Consider unconditionally throwing an exception instead.
2070+
fun buildReturnNullExclExclBlock() = (
2071+
FirSingleExpressionBlock(
2072+
buildReturnExpression {
2073+
this.target = target
2074+
result = buildCheckNotNullCall {
2075+
argumentList = buildUnaryArgumentList(
2076+
buildLiteralExpression(null, ConstantValueKind.Null, null, setType = true)
2077+
)
2078+
}
2079+
}
2080+
) to null)
2081+
2082+
val bodyWithContractDescription = if (headerCompilationMode) {
2083+
buildReturnNullExclExclBlock()
2084+
} else {
2085+
withForcedLocalContext {
2086+
convertFunctionBody(block, expression, allowLegacyContractDescription)
2087+
}
20472088
}
20482089
this.body = bodyWithContractDescription.first
20492090
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
@@ -2082,10 +2123,6 @@ class LightTreeRawFirDeclarationBuilder(
20822123
expression: LighterASTNode?,
20832124
allowLegacyContractDescription: Boolean
20842125
): Pair<FirBlock?, FirContractDescription?> {
2085-
// TODO-HEADER-COMPILATION: Another option to produce empty methods
2086-
// TODO-HEADER-COMPILATION: is to make this function return nothing.
2087-
if (headerCompilationMode)
2088-
return null to null
20892126
return when {
20902127
blockNode != null -> {
20912128
val block = convertBlock(blockNode)
@@ -2121,8 +2158,6 @@ class LightTreeRawFirDeclarationBuilder(
21212158
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseBlock
21222159
*/
21232160
fun convertBlock(block: LighterASTNode?): FirBlock {
2124-
// TODO-HEADER-COMPILATION: One option is to prevent the frontend
2125-
// TODO-HEADER-COMPILATION: from producing IR here.
21262161
if (block == null) return buildEmptyExpressionBlock()
21272162
if (block.tokenType != BLOCK) {
21282163
return FirSingleExpressionBlock(

0 commit comments

Comments
 (0)