[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:
Mikhail Zarechenskiy
2019-08-07 10:09:12 +03:00
parent 0219b86d06
commit 04e57f712e
29 changed files with 171 additions and 23 deletions
@@ -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()) {
@@ -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");
@@ -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
)
)
}
}
}
}
@@ -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))
}
@@ -92,6 +92,7 @@ class CallableReferenceResolver(
)
}
diagnosticsHolder.addDiagnosticIfNotNull(diagnostic)
chosenCandidate.diagnostics.forEach { diagnosticsHolder.addDiagnostic(it) }
chosenCandidate.freshSubstitutor = toFreshSubstitutor
} else {
if (candidates.isEmpty()) {
@@ -0,0 +1,4 @@
$TESTDATA_DIR$/functionReferenceWithDefaultValuesFeatureIsEnabledWithNewInference.kt
-d
$TEMP_DIR$
-Xnew-inference
@@ -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)
}
@@ -0,0 +1,4 @@
$TESTDATA_DIR$/functionReferenceWithDefaultValuesFeatureIsEnabledWithNewInference.kt
-d
$TEMP_DIR$
-XXLanguage\:+NewInference
@@ -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
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS
fun foo(s: String = "kotlin", vararg t: String): Boolean {
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS
// WITH_RUNTIME
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS
fun foo(vararg a: String, result: String = "OK"): String =
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
fun foo(x: String, y: Char = 'K'): String = x + y
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS
fun foo(x: String = "O", vararg y: String): String =
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS, JVM_IR
fun foo(vararg l: Long, s: String = "OK"): String =
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS
fun call0(f: (String) -> String, x: String): String = f(x)
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS
// WITH_RUNTIME
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
fun foo(x: String, y: String = "K"): String = x + y
@@ -1,4 +1,4 @@
// !LANGUAGE: +NewInference
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND: JS
fun foo(x: Int, s: Int, vararg y: CharSequence = arrayOf("Aaa")): String =
@@ -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)
}
@@ -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
@@ -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)
}
@@ -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");
@@ -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),