JVM_IR KT-24258 fix NPE message for delegated properties

This commit is contained in:
Dmitry Petrov
2020-12-23 17:19:02 +03:00
committed by TeamCityServer
parent ad8bed078f
commit 4e261cc358
11 changed files with 175 additions and 23 deletions

View File

@@ -16335,6 +16335,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt18911.kt");
}
@TestMetadata("kt24258.kt")
public void testKt24258() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258.kt");
}
@TestMetadata("kt24258nn.kt")
public void testKt24258nn() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258nn.kt");
}
@TestMetadata("localEntities.kt")
public void testLocalEntities() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/localEntities.kt");

View File

@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.isInlined
import org.jetbrains.kotlin.ir.util.render
@@ -148,7 +147,7 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
IrTypeOperator.IMPLICIT_NOTNULL -> {
val owner = scope.scopeOwnerSymbol.owner
val source = if (owner is IrFunction && owner.origin == IrDeclarationOrigin.DELEGATED_MEMBER) {
val source = if (owner is IrFunction && owner.isDelegated()) {
"${owner.name.asString()}(...)"
} else {
val (startOffset, endOffset) = expression.extents()
@@ -173,6 +172,10 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
}
}
private fun IrFunction.isDelegated() =
origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR ||
origin == IrDeclarationOrigin.DELEGATED_MEMBER
private fun IrElement.extents(): Pair<Int, Int> {
var startOffset = UNDEFINED_OFFSET
var endOffset = UNDEFINED_OFFSET

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irReturn
@@ -27,6 +28,7 @@ import org.jetbrains.kotlin.ir.descriptors.IrLocalDelegatedPropertyDelegateDescr
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
@@ -391,21 +393,17 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
irPropertyReference: IrCallableReference<*>
): IrBody =
with(createBodyGenerator(irGetter.symbol)) {
val startOffset = ktDelegate.startOffsetSkippingComments
val endOffset = ktDelegate.endOffset
val ktDelegateExpression = ktDelegate.expression!!
val startOffset = ktDelegateExpression.startOffsetSkippingComments
val endOffset = ktDelegateExpression.endOffset
irBlockBody(startOffset, endOffset) {
val statementGenerator = createStatementGenerator()
val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor)
val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall)
conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue)
updateNullThisRefValue(conventionMethodCall)
conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference
+irReturn(
CallGenerator(statementGenerator).generateCall(
startOffset,
endOffset,
conventionMethodCall
)
)
+irReturn(CallGenerator(statementGenerator).generateCall(startOffset, endOffset, conventionMethodCall))
}
}
@@ -415,18 +413,29 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
setterDescriptor: VariableAccessorDescriptor,
delegateReceiverValue: IntermediateValue,
irPropertyReference: IrCallableReference<*>
): IrBody = with(createBodyGenerator(irSetter.symbol)) {
val startOffset = ktDelegate.startOffsetSkippingComments
val endOffset = ktDelegate.endOffset
irBlockBody(startOffset, endOffset) {
val statementGenerator = createStatementGenerator()
val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor)
val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall)
conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue)
conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference
val irSetterParameter = irSetter.valueParameters[0]
conventionMethodCall.irValueArgumentsByIndex[2] = irGet(irSetterParameter.type, irSetterParameter.symbol)
+irReturn(CallGenerator(statementGenerator).generateCall(startOffset, endOffset, conventionMethodCall))
): IrBody =
with(createBodyGenerator(irSetter.symbol)) {
val ktDelegateExpression = ktDelegate.expression!!
val startOffset = ktDelegateExpression.startOffsetSkippingComments
val endOffset = ktDelegateExpression.endOffset
irBlockBody(startOffset, endOffset) {
val statementGenerator = createStatementGenerator()
val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor)
val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall)
conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue)
updateNullThisRefValue(conventionMethodCall)
conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference
val irSetterParameter = irSetter.valueParameters[0]
conventionMethodCall.irValueArgumentsByIndex[2] = irGet(irSetterParameter)
+irReturn(CallGenerator(statementGenerator).generateCall(startOffset, endOffset, conventionMethodCall))
}
}
private fun updateNullThisRefValue(conventionMethodCall: CallBuilder) {
val arg0 = conventionMethodCall.irValueArgumentsByIndex[0]
if (arg0 is IrConstImpl<*> && arg0.kind == IrConstKind.Null) {
conventionMethodCall.irValueArgumentsByIndex[0] =
IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.nothingNType)
}
}
}

View File

@@ -0,0 +1,28 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// WITH_RUNTIME
// FILE: kt24258.kt
val lazyNullString: String by lazy { J.nullString() }
fun testLazyNullString() {
try {
val s: String = lazyNullString
throw Exception("'val s: String = lazyNullString' should throw NullPointerException")
} catch (e: NullPointerException) {
}
}
fun box(): String {
testLazyNullString()
return "OK"
}
// FILE: J.java
public class J {
public static String nullString() {
return null;
}
}

View File

@@ -0,0 +1,30 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: kt24258nn.kt
val lazyNotNullString: String by lazy { J.nullNotNullString() }
fun testLazyNullNotNullString() {
try {
val s: String = lazyNotNullString
throw Exception("'val s: String = lazyNotNullString' should throw NullPointerException")
} catch (e: NullPointerException) {
}
}
fun box(): String {
testLazyNullNotNullString()
return "OK"
}
// FILE: J.java
import org.jetbrains.annotations.NotNull;
public class J {
@NotNull
public static String nullNotNullString() {
return null;
}
}

View File

@@ -0,0 +1,15 @@
// WITH_RUNTIME
// FILE: kt24258.kt
val lazyNullString: String by lazy { J.nullString() }
fun testLazyNullString() {
val s: String = lazyNullString
}
// FILE: J.java
public class J {
public static String nullString() {
return null;
}
}

View File

@@ -0,0 +1,22 @@
@0:0..9:0 FILE fqName:<root> fileName:/kt24258.kt
@3:0..53 PROPERTY name:lazyNullString visibility:public modality:FINAL [delegated,val]
@3:27..53 FIELD PROPERTY_DELEGATE name:lazyNullString$delegate type:kotlin.Lazy<@[FlexibleNullability] kotlin.String?> visibility:private [final,static]
@3:30..53 EXPRESSION_BODY
@3:30..53 CALL 'public final fun lazy <T> (initializer: kotlin.Function0<T of kotlin.lazy>): kotlin.Lazy<T of kotlin.lazy> declared in kotlin' type=kotlin.Lazy<@[FlexibleNullability] kotlin.String?> origin=null
@3:35..53 FUN_EXPR type=kotlin.Function0<@[FlexibleNullability] kotlin.String?> origin=LAMBDA
@3:35..53 FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String?
@3:37..51 BLOCK_BODY
@3:39..51 RETURN type=kotlin.Nothing from='local final fun <anonymous> (): @[FlexibleNullability] kotlin.String? declared in <root>.lazyNullString$delegate'
@3:39..51 CALL 'public open fun nullString (): @[FlexibleNullability] kotlin.String? declared in <root>.J' type=@[FlexibleNullability] kotlin.String? origin=null
@3:27..53 FUN DELEGATED_PROPERTY_ACCESSOR name:<get-lazyNullString> visibility:public modality:FINAL <> () returnType:kotlin.String
@3:30..53 BLOCK_BODY
@3:30..53 RETURN type=kotlin.Nothing from='public final fun <get-lazyNullString> (): kotlin.String declared in <root>'
@3:30..53 TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String
@3:30..53 CALL 'public final fun getValue <T> (thisRef: kotlin.Any?, property: kotlin.reflect.KProperty<*>): T of kotlin.getValue [inline,operator] declared in kotlin' type=@[FlexibleNullability] kotlin.String? origin=null
@3:27..53 GET_FIELD 'FIELD PROPERTY_DELEGATE name:lazyNullString$delegate type:kotlin.Lazy<@[FlexibleNullability] kotlin.String?> visibility:private [final,static]' type=kotlin.Lazy<@[FlexibleNullability] kotlin.String?> origin=null
@-1:-1..-1 CONST Null type=kotlin.Nothing? value=null
@3:27..53 PROPERTY_REFERENCE 'public final lazyNullString: kotlin.String [delegated,val]' field=null getter='public final fun <get-lazyNullString> (): kotlin.String declared in <root>' setter=null type=kotlin.reflect.KProperty0<kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE
@5:0..7:1 FUN name:testLazyNullString visibility:public modality:FINAL <> () returnType:kotlin.Unit
@5:25..7:1 BLOCK_BODY
@6:4..34 VAR name:s type:kotlin.String [val]
@6:20..34 CALL 'public final fun <get-lazyNullString> (): kotlin.String declared in <root>' type=kotlin.String origin=GET_PROPERTY

View File

@@ -16335,6 +16335,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt18911.kt");
}
@TestMetadata("kt24258.kt")
public void testKt24258() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258.kt");
}
@TestMetadata("kt24258nn.kt")
public void testKt24258nn() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258nn.kt");
}
@TestMetadata("localEntities.kt")
public void testLocalEntities() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/localEntities.kt");

View File

@@ -16287,6 +16287,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NotNullAssertions extends AbstractLightAnalysisModeTest {
@TestMetadata("kt24258.kt")
public void ignoreKt24258() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@@ -16335,6 +16340,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt18911.kt");
}
@TestMetadata("kt24258nn.kt")
public void testKt24258nn() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258nn.kt");
}
@TestMetadata("localEntities.kt")
public void testLocalEntities() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/localEntities.kt");

View File

@@ -16335,6 +16335,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt18911.kt");
}
@TestMetadata("kt24258.kt")
public void testKt24258() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258.kt");
}
@TestMetadata("kt24258nn.kt")
public void testKt24258nn() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258nn.kt");
}
@TestMetadata("localEntities.kt")
public void testLocalEntities() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/localEntities.kt");

View File

@@ -44,6 +44,11 @@ public class IrSourceRangesTestCaseGenerated extends AbstractIrSourceRangesTestC
runTest("compiler/testData/ir/sourceRanges/kt17108.kt");
}
@TestMetadata("kt24258.kt")
public void testKt24258() throws Exception {
runTest("compiler/testData/ir/sourceRanges/kt24258.kt");
}
@TestMetadata("compiler/testData/ir/sourceRanges/declarations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)