KT-47939 fun interface constructor reference should throw NPE for null

This commit is contained in:
Dmitry Petrov
2021-12-07 15:09:24 +03:00
committed by TeamCityServer
parent e5eee9bab9
commit 0ccd7a7e0c
15 changed files with 245 additions and 102 deletions
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.synthetic.FunctionInterfaceConstructorDescriptor
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
@@ -43,6 +44,8 @@ import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
@@ -88,7 +91,7 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
statementGenerator.generateCallReceiver(
ktCallableReference,
resolvedDescriptor,
resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,resolvedCall.contextReceivers,
resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, resolvedCall.contextReceivers,
isSafe = false
).call { dispatchReceiverValue, extensionReceiverValue, _ ->
generateCallableReference(
@@ -119,7 +122,7 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
): IrExpression {
// {
// fun <ADAPTER_FUN>(function: <FUN_TYPE>): <FUN_INTERFACE_TYPE> =
// <FUN_INTERFACE_TYPE>(function)
// <FUN_INTERFACE_TYPE>(function!!)
// ::<ADAPTER_FUN>
// }
val startOffset = ktCallableReference.startOffsetSkippingComments
@@ -176,23 +179,40 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
irAdapterFun.dispatchReceiverParameter = null
irAdapterFun.extensionReceiverParameter = null
val irFnParameter = createAdapterParameter(startOffset, endOffset, functionParameter.name, 0, functionParameter.type)
val fnType = functionParameter.type
val irFnParameter = createAdapterParameter(startOffset, endOffset, functionParameter.name, 0, fnType)
val irFnType = irFnParameter.type
val checkNotNull = context.irBuiltIns.checkNotNullSymbol.descriptor
val checkNotNullSubstituted =
checkNotNull.substitute(
TypeSubstitutor.create(
mapOf(checkNotNull.typeParameters[0].typeConstructor to TypeProjectionImpl(fnType))
)
) ?: throw AssertionError("Substitution failed for $checkNotNull: T=$fnType")
irAdapterFun.valueParameters = listOf(irFnParameter)
irAdapterFun.body =
context.irFactory.createBlockBody(
startOffset, endOffset,
listOf(
IrReturnImpl(
startOffset, endOffset, context.irBuiltIns.nothingType,
irAdapterFun.symbol,
IrTypeOperatorCallImpl(
startOffset, endOffset,
irSamType, IrTypeOperator.SAM_CONVERSION, irSamType,
IrGetValueImpl(startOffset, endOffset, irFnParameter.symbol)
)
IrBlockBodyBuilder(
context,
Scope(irAdapterFun.symbol),
startOffset,
endOffset
).blockBody {
+irReturn(
irSamConversion(
irCall(context.irBuiltIns.checkNotNullSymbol).also { irCall ->
this@ReflectionReferencesGenerator.context.callToSubstitutedDescriptorMap[irCall] =
checkNotNullSubstituted
irCall.type = irFnType
irCall.putTypeArgument(0, irFnType)
irCall.putValueArgument(0, irGet(irFnParameter))
},
irSamType
)
)
)
}
}
}
}
@@ -317,6 +317,9 @@ fun IrBuilderWithScope.irImplicitCast(argument: IrExpression, type: IrType) =
fun IrBuilderWithScope.irReinterpretCast(argument: IrExpression, type: IrType) =
IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.REINTERPRET_CAST, type, argument)
fun IrBuilderWithScope.irSamConversion(argument: IrExpression, type: IrType) =
typeOperator(type, argument, IrTypeOperator.SAM_CONVERSION, type)
fun IrBuilderWithScope.irInt(value: Int, type: IrType = context.irBuiltIns.intType) =
IrConstImpl.int(startOffset, endOffset, type, value)
@@ -96,9 +96,22 @@ class IrBuiltInsOverDescriptors(
val symbol = symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) {
val operator = irFactory.createFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, it, Name.identifier(name), DescriptorVisibilities.PUBLIC, Modality.FINAL,
returnType, isInline = false, isExternal = false, isTailrec = false, isSuspend = false,
isOperator = false, isInfix = false, isExpect = false, isFakeOverride = false
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
BUILTIN_OPERATOR,
it,
Name.identifier(name),
DescriptorVisibilities.PUBLIC,
Modality.FINAL,
returnType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = false,
isOperator = false,
isInfix = false,
isExpect = false,
isFakeOverride = false
)
operator.parent = operatorsPackageFragment
operatorsPackageFragment.declarations += operator
@@ -160,49 +173,53 @@ class IrBuiltInsOverDescriptors(
)
}
val typeParameterSymbol = IrTypeParameterSymbolImpl(typeParameterDescriptor)
val typeParameter = irFactory.createTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, typeParameterSymbol, Name.identifier("T0"), 0, true, Variance.INVARIANT
).apply {
superTypes += anyType
}
return symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) { operatorSymbol ->
val typeParameter = symbolTable.declareGlobalTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
BUILTIN_OPERATOR,
typeParameterDescriptor
).apply {
superTypes += anyType
}
val typeParameterSymbol = typeParameter.symbol
val returnIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = returnKotlinType
hasQuestionMark = false
buildSimpleType()
}
val returnIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = returnKotlinType
hasQuestionMark = false
buildSimpleType()
}
val valueIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = valueKotlinType
hasQuestionMark = true
buildSimpleType()
}
val valueIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = valueKotlinType
hasQuestionMark = true
buildSimpleType()
}
return symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) {
val operator = irFactory.createFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, it, name, DescriptorVisibilities.PUBLIC, Modality.FINAL, returnIrType,
irFactory.createFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR,
operatorSymbol, name,
DescriptorVisibilities.PUBLIC, Modality.FINAL,
returnIrType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = false, isInfix = false,
isExpect = false, isFakeOverride = false
)
operator.parent = operatorsPackageFragment
operatorsPackageFragment.declarations += operator
).also { operator ->
operator.parent = operatorsPackageFragment
operatorsPackageFragment.declarations += operator
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
val valueParameter = irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg0"), 0,
valueIrType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
)
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
val valueParameter = irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg0"), 0,
valueIrType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
)
valueParameter.parent = operator
typeParameter.parent = operator
valueParameter.parent = operator
typeParameter.parent = operator
operator.valueParameters += valueParameter
operator.typeParameters += typeParameter
operator
operator.valueParameters += valueParameter
operator.typeParameters += typeParameter
}
}.symbol
}
@@ -265,6 +282,7 @@ class IrBuiltInsOverDescriptors(
val string = builtIns.stringType
override val stringType = string.toIrType()
override val stringClass = builtIns.string.toIrSymbol()
// TODO: check if correct
override val charSequenceClass = findClass(Name.identifier("CharSequence"), "kotlin")!!
@@ -341,7 +359,8 @@ class IrBuiltInsOverDescriptors(
override val doubleArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.DOUBLE).toIrSymbol()
override val booleanArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.BOOLEAN).toIrSymbol()
override val primitiveArraysToPrimitiveTypes = PrimitiveType.values().associate { builtIns.getPrimitiveArrayClassDescriptor(it).toIrSymbol() to it }
override val primitiveArraysToPrimitiveTypes =
PrimitiveType.values().associate { builtIns.getPrimitiveArrayClassDescriptor(it).toIrSymbol() to it }
override val primitiveTypesToPrimitiveArrays = primitiveArraysToPrimitiveTypes.map { (k, v) -> v to k }.toMap()
override val primitiveArrayElementTypes = primitiveArraysToPrimitiveTypes.mapValues { primitiveTypeToIrType[it.value] }
override val primitiveArrayForType = primitiveArrayElementTypes.asSequence().associate { it.value to it.key }
@@ -353,16 +372,24 @@ class IrBuiltInsOverDescriptors(
}.toMap()
override val lessFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS)
override val lessOrEqualFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS_OR_EQUAL)
override val greaterOrEqualFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER_OR_EQUAL)
override val greaterFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER)
override val lessOrEqualFunByOperandType =
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS_OR_EQUAL)
override val greaterOrEqualFunByOperandType =
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER_OR_EQUAL)
override val greaterFunByOperandType =
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER)
override val ieee754equalsFunByOperandType =
primitiveFloatingPointIrTypes.map {
it.classifierOrFail to defineOperator(BuiltInOperatorNames.IEEE754_EQUALS, booleanType, listOf(it.makeNullable(), it.makeNullable()))
it.classifierOrFail to defineOperator(
BuiltInOperatorNames.IEEE754_EQUALS,
booleanType,
listOf(it.makeNullable(), it.makeNullable())
)
}.toMap()
val booleanNot = builtIns.boolean.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("not"), NoLookupLocation.FROM_BACKEND).single()
val booleanNot =
builtIns.boolean.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("not"), NoLookupLocation.FROM_BACKEND).single()
override val booleanNotSymbol = symbolTable.referenceSimpleFunction(booleanNot)
override val eqeqeqSymbol = defineOperator(BuiltInOperatorNames.EQEQEQ, booleanType, listOf(anyNType, anyNType))
@@ -371,8 +398,10 @@ class IrBuiltInsOverDescriptors(
override val throwIseSymbol = defineOperator(BuiltInOperatorNames.THROW_ISE, nothingType, listOf())
override val andandSymbol = defineOperator(BuiltInOperatorNames.ANDAND, booleanType, listOf(booleanType, booleanType))
override val ororSymbol = defineOperator(BuiltInOperatorNames.OROR, booleanType, listOf(booleanType, booleanType))
override val noWhenBranchMatchedExceptionSymbol = defineOperator(BuiltInOperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothingType, listOf())
override val illegalArgumentExceptionSymbol = defineOperator(BuiltInOperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothingType, listOf(stringType))
override val noWhenBranchMatchedExceptionSymbol =
defineOperator(BuiltInOperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothingType, listOf())
override val illegalArgumentExceptionSymbol =
defineOperator(BuiltInOperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothingType, listOf(stringType))
override val checkNotNullSymbol = defineCheckNotNullOperator()
@@ -476,7 +505,7 @@ class IrBuiltInsOverDescriptors(
}
}
private fun <T: Any> getFunctionsByKey(
private fun <T : Any> getFunctionsByKey(
name: Name,
vararg packageNameSegments: String,
makeKey: (SimpleFunctionDescriptor) -> T?
@@ -1129,7 +1129,7 @@ fun SymbolTable.noUnboundLeft(message: String) {
assert(unbound.isEmpty()) {
"$message\n" +
unbound.joinToString("\n") {
"$it ${it.signature?.toString() ?: "(NON-PUBLIC API)"}: ${it.descriptor}"
"${it::class.simpleName} $it ${it.signature?.toString() ?: "(NON-PUBLIC API)"}: ${it.descriptor}"
}
}
}