[NI] Introduce feature for passing function references with defaults
Relates to KT-8834, we continue reducing differences between old and new inference. Note that as for `SamConversionPerArgument`, this feature is enabled in the compiler and not in the IDE to avoid breaking code for those users that already enabled new inference in the compiler
This commit is contained in:
+16
-4
@@ -336,6 +336,7 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
if (newInference) {
|
||||
put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED)
|
||||
put(LanguageFeature.SamConversionPerArgument, LanguageFeature.State.ENABLED)
|
||||
put(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (inlineClasses) {
|
||||
@@ -382,19 +383,30 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
val featuresThatForcePreReleaseBinaries = mutableListOf<LanguageFeature>()
|
||||
|
||||
var standaloneSamConversionFeaturePassedExplicitly = false
|
||||
var functionReferenceWithDefaultValueFeaturePassedExplicitly = false
|
||||
for ((feature, state) in internalArguments.filterIsInstance<ManualLanguageFeatureSetting>()) {
|
||||
put(feature, state)
|
||||
if (state == LanguageFeature.State.ENABLED && feature.forcesPreReleaseBinariesIfEnabled()) {
|
||||
featuresThatForcePreReleaseBinaries += feature
|
||||
}
|
||||
|
||||
if (feature == LanguageFeature.SamConversionPerArgument) {
|
||||
standaloneSamConversionFeaturePassedExplicitly = true
|
||||
when (feature) {
|
||||
LanguageFeature.SamConversionPerArgument ->
|
||||
standaloneSamConversionFeaturePassedExplicitly = true
|
||||
|
||||
LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType ->
|
||||
functionReferenceWithDefaultValueFeaturePassedExplicitly = true
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
if (!standaloneSamConversionFeaturePassedExplicitly && this[LanguageFeature.NewInference] == LanguageFeature.State.ENABLED) {
|
||||
put(LanguageFeature.SamConversionPerArgument, LanguageFeature.State.ENABLED)
|
||||
if (this[LanguageFeature.NewInference] == LanguageFeature.State.ENABLED) {
|
||||
if (!standaloneSamConversionFeaturePassedExplicitly)
|
||||
put(LanguageFeature.SamConversionPerArgument, LanguageFeature.State.ENABLED)
|
||||
|
||||
if (!functionReferenceWithDefaultValueFeaturePassedExplicitly)
|
||||
put(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (featuresThatForcePreReleaseBinaries.isNotEmpty()) {
|
||||
|
||||
+10
@@ -1707,6 +1707,16 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/expectedTypeAsSubtypeOfFunctionType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceWithDefaultValueAsOtherFunctionType.kt")
|
||||
public void testFunctionReferenceWithDefaultValueAsOtherFunctionType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceWithDefaultValueAsOtherFunctionType_enabled.kt")
|
||||
public void testFunctionReferenceWithDefaultValueAsOtherFunctionType_enabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType_enabled.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt15439_completeCall.kt")
|
||||
public void testKt15439_completeCall() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/kt15439_completeCall.kt");
|
||||
|
||||
+16
-1
@@ -5,10 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls
|
||||
|
||||
import com.intellij.psi.util.PsiUtil
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE
|
||||
@@ -148,6 +148,21 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CallableReferencesDefaultArgumentUsed::class.java -> {
|
||||
require(diagnostic is CallableReferencesDefaultArgumentUsed) {
|
||||
"diagnostic ($diagnostic) should have type CallableReferencesDefaultArgumentUsed"
|
||||
}
|
||||
|
||||
diagnostic.argument.psiExpression?.let {
|
||||
trace.report(
|
||||
UNSUPPORTED_FEATURE.on(
|
||||
it, LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType to context.languageVersionSettings
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.calls.components.CreateFreshVariablesSubstitutor.createToFreshVariableSubstitutorAndAddInitialConstraints
|
||||
@@ -180,7 +181,9 @@ class CallableReferencesCandidateFactory(
|
||||
expectedType
|
||||
)
|
||||
|
||||
if (defaults != 0) {
|
||||
if (defaults != 0 &&
|
||||
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType)
|
||||
) {
|
||||
diagnostics.add(CallableReferencesDefaultArgumentUsed(argument, candidateDescriptor, defaults))
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -92,6 +92,7 @@ class CallableReferenceResolver(
|
||||
)
|
||||
}
|
||||
diagnosticsHolder.addDiagnosticIfNotNull(diagnostic)
|
||||
chosenCandidate.diagnostics.forEach { diagnosticsHolder.addDiagnostic(it) }
|
||||
chosenCandidate.freshSubstitutor = toFreshSubstitutor
|
||||
} else {
|
||||
if (candidates.isEmpty()) {
|
||||
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
$TESTDATA_DIR$/functionReferenceWithDefaultValuesFeatureIsEnabledWithNewInference.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-Xnew-inference
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fun foo(a: String, b: Int = 5): String {
|
||||
return a + b
|
||||
}
|
||||
|
||||
fun bar1(body: (String) -> String): String {
|
||||
return body("something")
|
||||
}
|
||||
|
||||
fun test() {
|
||||
bar1(::foo)
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
OK
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
$TESTDATA_DIR$/functionReferenceWithDefaultValuesFeatureIsEnabledWithNewInference.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-XXLanguage\:+NewInference
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
warning: ATTENTION!
|
||||
This build uses unsafe internal compiler arguments:
|
||||
|
||||
-XXLanguage:+NewInference
|
||||
|
||||
This mode is not recommended for production use,
|
||||
as no stability/compatibility guarantees are given on
|
||||
compiler or generated code. Use it at your own risk!
|
||||
|
||||
OK
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
fun foo(s: String = "kotlin", vararg t: String): Boolean {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
fun foo(vararg a: String, result: String = "OK"): String =
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
|
||||
fun foo(x: String, y: Char = 'K'): String = x + y
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
fun foo(x: String = "O", vararg y: String): String =
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS, JVM_IR
|
||||
|
||||
fun foo(vararg l: Long, s: String = "OK"): String =
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
fun call0(f: (String) -> String, x: String): String = f(x)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
|
||||
fun foo(x: String, y: String = "K"): String = x + y
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
fun foo(x: Int, s: Int, vararg y: CharSequence = arrayOf("Aaa")): String =
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
fun foo(a: String, b: Int = 5): String {
|
||||
return a + b
|
||||
}
|
||||
|
||||
fun bar1(body: (String) -> String): String {
|
||||
return body("something")
|
||||
}
|
||||
|
||||
fun bar2(body: (String, Int) -> String): String {
|
||||
return body("something", 0)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
bar1(<!NI;UNSUPPORTED_FEATURE, OI;TYPE_MISMATCH!>::foo<!>)
|
||||
bar2(::foo)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public fun bar1(/*0*/ body: (kotlin.String) -> kotlin.String): kotlin.String
|
||||
public fun bar2(/*0*/ body: (kotlin.String, kotlin.Int) -> kotlin.String): kotlin.String
|
||||
public fun foo(/*0*/ a: kotlin.String, /*1*/ b: kotlin.Int = ...): kotlin.String
|
||||
public fun test(): kotlin.Unit
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
|
||||
|
||||
fun foo(a: String, b: Int = 5): String {
|
||||
return a + b
|
||||
}
|
||||
|
||||
fun bar1(body: (String) -> String): String {
|
||||
return body("something")
|
||||
}
|
||||
|
||||
fun bar2(body: (String, Int) -> String): String {
|
||||
return body("something", 0)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
bar1(::foo)
|
||||
bar2(::foo)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public fun bar1(/*0*/ body: (kotlin.String) -> kotlin.String): kotlin.String
|
||||
public fun bar2(/*0*/ body: (kotlin.String, kotlin.Int) -> kotlin.String): kotlin.String
|
||||
public fun foo(/*0*/ a: kotlin.String, /*1*/ b: kotlin.Int = ...): kotlin.String
|
||||
public fun test(): kotlin.Unit
|
||||
@@ -1714,6 +1714,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/expectedTypeAsSubtypeOfFunctionType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceWithDefaultValueAsOtherFunctionType.kt")
|
||||
public void testFunctionReferenceWithDefaultValueAsOtherFunctionType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceWithDefaultValueAsOtherFunctionType_enabled.kt")
|
||||
public void testFunctionReferenceWithDefaultValueAsOtherFunctionType_enabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType_enabled.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt15439_completeCall.kt")
|
||||
public void testKt15439_completeCall() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/kt15439_completeCall.kt");
|
||||
|
||||
Generated
+10
@@ -1709,6 +1709,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/expectedTypeAsSubtypeOfFunctionType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceWithDefaultValueAsOtherFunctionType.kt")
|
||||
public void testFunctionReferenceWithDefaultValueAsOtherFunctionType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceWithDefaultValueAsOtherFunctionType_enabled.kt")
|
||||
public void testFunctionReferenceWithDefaultValueAsOtherFunctionType_enabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/functionReferenceWithDefaultValueAsOtherFunctionType_enabled.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt15439_completeCall.kt")
|
||||
public void testKt15439_completeCall() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/kt15439_completeCall.kt");
|
||||
|
||||
@@ -266,6 +266,16 @@ public class CliTestGenerated extends AbstractCliTest {
|
||||
runTest("compiler/testData/cli/jvm/flagAllowingResultAsReturnType.args");
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceWithDefaultValuesFeatureIsEnabledWithNewInference.args")
|
||||
public void testFunctionReferenceWithDefaultValuesFeatureIsEnabledWithNewInference() throws Exception {
|
||||
runTest("compiler/testData/cli/jvm/functionReferenceWithDefaultValuesFeatureIsEnabledWithNewInference.args");
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceWithDefaultValuesFeatureIsEnabledWithXXNewInference.args")
|
||||
public void testFunctionReferenceWithDefaultValuesFeatureIsEnabledWithXXNewInference() throws Exception {
|
||||
runTest("compiler/testData/cli/jvm/functionReferenceWithDefaultValuesFeatureIsEnabledWithXXNewInference.args");
|
||||
}
|
||||
|
||||
@TestMetadata("help.args")
|
||||
public void testHelp() throws Exception {
|
||||
runTest("compiler/testData/cli/jvm/help.args");
|
||||
|
||||
@@ -123,15 +123,14 @@ enum class LanguageFeature(
|
||||
MultiPlatformProjects(sinceVersion = null, defaultState = State.DISABLED),
|
||||
|
||||
NewInference(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED),
|
||||
// This feature can be enabled only along with new inference, see KT-26357 for details
|
||||
BooleanElvisBoundSmartCasts(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED),
|
||||
|
||||
// In the next block, features can be enabled only along with new inference
|
||||
BooleanElvisBoundSmartCasts(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED), // see KT-26357 for details
|
||||
SamConversionForKotlinFunctions(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED),
|
||||
|
||||
SamConversionPerArgument(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED),
|
||||
|
||||
// can be used only with NewInference feature
|
||||
NewDataFlowForTryExpressions(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED),
|
||||
FunctionReferenceWithDefaultValueAsOtherType(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED),
|
||||
// ------
|
||||
// Next features can be enabled regardless of new inference
|
||||
|
||||
InlineClasses(sinceVersion = KOTLIN_1_3, defaultState = State.ENABLED_WITH_WARNING, kind = UNSTABLE_FEATURE),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user