mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-19 00:21:28 +00:00
JVM_IR KT-24258 fix NPE message for delegated properties
This commit is contained in:
committed by
TeamCityServer
parent
ad8bed078f
commit
4e261cc358
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258.kt
vendored
Normal file
28
compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258.kt
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
30
compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258nn.kt
vendored
Normal file
30
compiler/testData/codegen/box/javaInterop/notNullAssertions/kt24258nn.kt
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
15
compiler/testData/ir/sourceRanges/kt24258.kt
vendored
Normal file
15
compiler/testData/ir/sourceRanges/kt24258.kt
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
22
compiler/testData/ir/sourceRanges/kt24258.txt
vendored
Normal file
22
compiler/testData/ir/sourceRanges/kt24258.txt
vendored
Normal 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
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user