mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-16 15:52:18 +00:00
Don't recognize nullable function types as inlinable
#KT-19679 Fixed
This commit is contained in:
@@ -529,7 +529,7 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
||||
val varDescriptor = field.descriptor
|
||||
//check that variable is inline function parameter
|
||||
return !(varDescriptor is ParameterDescriptor &&
|
||||
InlineUtil.isInlineLambdaParameter(varDescriptor) &&
|
||||
InlineUtil.isInlineParameter(varDescriptor) &&
|
||||
InlineUtil.isInline(varDescriptor.containingDeclaration))
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ class PsiInlineCodegen(
|
||||
//TODO deparenthisise typed
|
||||
val deparenthesized = KtPsiUtil.deparenthesize(expression)
|
||||
|
||||
return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) && isInlinableParameterExpression(deparenthesized)
|
||||
return InlineUtil.isInlineParameter(valueParameterDescriptor) && isInlinableParameterExpression(deparenthesized)
|
||||
}
|
||||
|
||||
override fun genValueAndPut(
|
||||
|
||||
@@ -51,7 +51,7 @@ fun extractDefaultLambdaOffsetAndDescriptor(jvmSignature: JvmMethodSignature, fu
|
||||
val valueParameterOffset = valueParameters.takeWhile { it.kind != JvmMethodParameterKind.VALUE }.size
|
||||
|
||||
return functionDescriptor.valueParameters.filter {
|
||||
InlineUtil.isInlineLambdaParameter(it) && it.declaresDefaultValue()
|
||||
InlineUtil.isInlineParameter(it) && it.declaresDefaultValue()
|
||||
}.associateBy {
|
||||
parameterOffsets[valueParameterOffset + it.index]
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
|
||||
private val isEffectivelyPrivateApiFunction = descriptor.isEffectivelyPrivateApi
|
||||
|
||||
private val inlinableParameters = descriptor.valueParameters.filter { isInlinableParameter(it) }
|
||||
private val inlinableParameters = descriptor.valueParameters.filter { InlineUtil.isInlineParameter(it) }
|
||||
|
||||
private val inlinableKtParameters = inlinableParameters.mapNotNull { (it.source as? KotlinSourceElement)?.psi }
|
||||
|
||||
@@ -132,7 +132,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
when {
|
||||
!checkNotInDefaultParameter(context, argumentCallee, argumentExpression) -> { /*error*/ }
|
||||
|
||||
InlineUtil.isInline(targetDescriptor) && isInlinableParameter(targetParameterDescriptor) ->
|
||||
InlineUtil.isInline(targetDescriptor) && InlineUtil.isInlineParameter(targetParameterDescriptor) ->
|
||||
if (allowsNonLocalReturns(argumentCallee) && !allowsNonLocalReturns(targetParameterDescriptor)) {
|
||||
context.trace.report(NON_LOCAL_RETURN_NOT_ALLOWED.on(argumentExpression, argumentExpression))
|
||||
}
|
||||
@@ -219,10 +219,6 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
}
|
||||
}
|
||||
|
||||
private fun isInlinableParameter(descriptor: ParameterDescriptor): Boolean {
|
||||
return InlineUtil.isInlineLambdaParameter(descriptor) && !descriptor.type.isMarkedNullable
|
||||
}
|
||||
|
||||
private fun isInvokeOrInlineExtension(descriptor: CallableDescriptor): Boolean {
|
||||
if (descriptor !is SimpleFunctionDescriptor) {
|
||||
return false
|
||||
|
||||
@@ -154,9 +154,12 @@ class InlineAnalyzerExtension(
|
||||
}
|
||||
|
||||
private fun checkHasInlinableAndNullability(functionDescriptor: FunctionDescriptor, function: KtFunction, trace: BindingTrace) {
|
||||
for ((parameter, descriptor) in function.valueParameters.zip(functionDescriptor.valueParameters)) {
|
||||
if (checkInlinableParameter(descriptor, parameter, functionDescriptor, trace)) return
|
||||
var hasInlineArgs = false
|
||||
function.valueParameters.zip(functionDescriptor.valueParameters).forEach {
|
||||
(parameter, descriptor) ->
|
||||
hasInlineArgs = hasInlineArgs or checkInlinableParameter(descriptor, parameter, functionDescriptor, trace)
|
||||
}
|
||||
if (hasInlineArgs) return
|
||||
|
||||
if (functionDescriptor.isInlineOnlyOrReifiable() || functionDescriptor.isHeader) return
|
||||
|
||||
@@ -171,7 +174,7 @@ class InlineAnalyzerExtension(
|
||||
expression: KtElement,
|
||||
functionDescriptor: CallableDescriptor,
|
||||
trace: BindingTrace?): Boolean {
|
||||
if (InlineUtil.isInlineLambdaParameter(parameter)) {
|
||||
if (InlineUtil.isInlineParameterExceptNullability(parameter)) {
|
||||
if (parameter.type.isMarkedNullable) {
|
||||
trace?.report(Errors.NULLABLE_INLINE_PARAMETER.on(expression, expression, functionDescriptor))
|
||||
}
|
||||
|
||||
@@ -32,12 +32,18 @@ import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
|
||||
public class InlineUtil {
|
||||
public static boolean isInlineLambdaParameter(@NotNull ParameterDescriptor valueParameterOrReceiver) {
|
||||
|
||||
public static boolean isInlineParameterExceptNullability(@NotNull ParameterDescriptor valueParameterOrReceiver) {
|
||||
return !(valueParameterOrReceiver instanceof ValueParameterDescriptor
|
||||
&& ((ValueParameterDescriptor) valueParameterOrReceiver).isNoinline()) &&
|
||||
FunctionTypesKt.isFunctionType(valueParameterOrReceiver.getOriginal().getType());
|
||||
}
|
||||
|
||||
public static boolean isInlineParameter(@NotNull ParameterDescriptor valueParameterOrReceiver) {
|
||||
return isInlineParameterExceptNullability(valueParameterOrReceiver) &&
|
||||
!valueParameterOrReceiver.getOriginal().getType().isMarkedNullable();
|
||||
}
|
||||
|
||||
public static boolean isInline(@Nullable DeclarationDescriptor descriptor) {
|
||||
return descriptor instanceof FunctionDescriptor && getInlineStrategy((FunctionDescriptor) descriptor).isInline();
|
||||
}
|
||||
@@ -152,7 +158,7 @@ public class InlineUtil {
|
||||
if (!(mapping instanceof ArgumentMatch)) return null;
|
||||
|
||||
ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter();
|
||||
return isInlineLambdaParameter(parameter) ? parameter : null;
|
||||
return isInlineParameter(parameter) ? parameter : null;
|
||||
}
|
||||
|
||||
public static boolean canBeInlineArgument(@Nullable PsiElement functionalExpression) {
|
||||
|
||||
19
compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679.kt
vendored
Normal file
19
compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679.kt
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// FILE: 1.kt
|
||||
package test
|
||||
|
||||
inline fun build(func: () -> Unit, noinline pathFunc: (() -> String)? = null) {
|
||||
func()
|
||||
|
||||
pathFunc?.invoke()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
var result = "fail"
|
||||
build({ result = "OK" })
|
||||
|
||||
return result
|
||||
}
|
||||
15
compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_2.kt
vendored
Normal file
15
compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_2.kt
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// FILE: 1.kt
|
||||
package test
|
||||
|
||||
inline fun build(noinline pathFunc: (() -> String)? = null) {
|
||||
pathFunc?.invoke()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
build ()
|
||||
return "OK"
|
||||
}
|
||||
20
compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_3.kt
vendored
Normal file
20
compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_3.kt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// FILE: 1.kt
|
||||
package test
|
||||
|
||||
@Suppress("NULLABLE_INLINE_PARAMETER")
|
||||
inline fun build(func: () -> Unit, pathFunc: (() -> String)? = null) {
|
||||
func()
|
||||
|
||||
pathFunc?.invoke()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
var result = "fail"
|
||||
build ({ result = "OK" })
|
||||
|
||||
return result
|
||||
}
|
||||
4
compiler/testData/diagnostics/tests/inline/kt19679.kt
vendored
Normal file
4
compiler/testData/diagnostics/tests/inline/kt19679.kt
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
inline fun test(s: () -> Unit, <!NULLABLE_INLINE_PARAMETER!>p: (() -> Unit)?<!>) {
|
||||
s()
|
||||
p?.invoke()
|
||||
}
|
||||
3
compiler/testData/diagnostics/tests/inline/kt19679.txt
vendored
Normal file
3
compiler/testData/diagnostics/tests/inline/kt19679.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public inline fun test(/*0*/ s: () -> kotlin.Unit, /*1*/ p: (() -> kotlin.Unit)?): kotlin.Unit
|
||||
@@ -1339,6 +1339,24 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679.kt")
|
||||
public void testKt19679() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_2.kt")
|
||||
public void testKt19679_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_3.kt")
|
||||
public void testKt19679_3() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt");
|
||||
|
||||
@@ -1339,6 +1339,24 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679.kt")
|
||||
public void testKt19679() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_2.kt")
|
||||
public void testKt19679_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_3.kt")
|
||||
public void testKt19679_3() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt");
|
||||
|
||||
@@ -11263,6 +11263,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679.kt")
|
||||
public void testKt19679() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/kt19679.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt4869.kt")
|
||||
public void testKt4869() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/kt4869.kt");
|
||||
|
||||
@@ -1339,6 +1339,24 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679.kt")
|
||||
public void testKt19679() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_2.kt")
|
||||
public void testKt19679_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_3.kt")
|
||||
public void testKt19679_3() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt");
|
||||
|
||||
@@ -1339,6 +1339,24 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679.kt")
|
||||
public void testKt19679() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_2.kt")
|
||||
public void testKt19679_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_3.kt")
|
||||
public void testKt19679_3() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt");
|
||||
|
||||
@@ -416,6 +416,24 @@ public class InlineDefaultValuesTestsGenerated extends AbstractInlineDefaultValu
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679.kt")
|
||||
public void testKt19679() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_2.kt")
|
||||
public void testKt19679_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt19679_3.kt")
|
||||
public void testKt19679_3() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/kt19679_3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElimination/simple.kt");
|
||||
|
||||
@@ -79,7 +79,7 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
||||
|
||||
if (descriptor instanceof ValueParameterDescriptor) {
|
||||
return InlineUtil.isInline(descriptor.getContainingDeclaration()) &&
|
||||
InlineUtil.isInlineLambdaParameter((ParameterDescriptor) descriptor) &&
|
||||
InlineUtil.isInlineParameter((ParameterDescriptor) descriptor) &&
|
||||
!((ValueParameterDescriptor) descriptor).isCrossinline();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user