Introduce language feature for type inference on generics for callable references
#KT-16061 Fixed
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -86,7 +86,8 @@ private val DEFAULT_CALL_CHECKERS = listOf(
|
||||
CapturingInClosureChecker(), InlineCheckerWrapper(), SafeCallChecker(),
|
||||
DeprecatedCallChecker, CallReturnsArrayOfNothingChecker(), InfixCallChecker(), OperatorCallChecker(),
|
||||
ConstructorHeaderCallChecker, ProtectedConstructorCallChecker, ApiVersionCallChecker,
|
||||
CoroutineSuspendCallChecker, BuilderFunctionsCallChecker, DslScopeViolationCallChecker
|
||||
CoroutineSuspendCallChecker, BuilderFunctionsCallChecker, DslScopeViolationCallChecker,
|
||||
CallableReferenceCompatibilityChecker()
|
||||
)
|
||||
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
|
||||
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker)
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isCallableReference
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class CallableReferenceCompatibilityChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val typeInferenceForCallableReferencesFeature = LanguageFeature.TypeInferenceOnGenericsForCallableReferences
|
||||
if (context.languageVersionSettings.supportsFeature(typeInferenceForCallableReferencesFeature)) return
|
||||
|
||||
for ((_, resolvedArgument) in resolvedCall.valueArguments) {
|
||||
inner@ for (argument in resolvedArgument.arguments) {
|
||||
val argumentExpression = argument.getArgumentExpression() as? KtCallableReferenceExpression ?: continue@inner
|
||||
val callableReferenceResolvedCall = argumentExpression.callableReference.getResolvedCall(context.trace.bindingContext) ?: continue@inner
|
||||
if (callableReferenceResolvedCall.call.isCallableReference() &&
|
||||
callableReferenceResolvedCall.candidateDescriptor.typeParameters.isNotEmpty()) {
|
||||
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(argumentExpression, typeInferenceForCallableReferencesFeature))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
// !LANGUAGE: -TypeInferenceOnGenericsForCallableReferences
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE, -UNUSED_PARAMETER
|
||||
|
||||
fun <T> bar(s: T) {}
|
||||
fun <T> complex(t: T, f: (T) -> Unit) {}
|
||||
fun <T> simple(f: (T) -> Unit) {}
|
||||
|
||||
fun test1() {
|
||||
complex(1, <!UNSUPPORTED_FEATURE!>::bar<!>)
|
||||
simple<String>(<!UNSUPPORTED_FEATURE!>::bar<!>)
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
fun <T> takeFun(f: (T) -> Unit) {}
|
||||
fun <T, R> callFun(f: (T) -> R): R = TODO()
|
||||
|
||||
fun <T> foo(s: T) {}
|
||||
|
||||
open class Wrapper<T>(val value: T)
|
||||
fun <T, R : Wrapper<in T>> createWrapper(s: T): R = TODO()
|
||||
|
||||
fun <T> Wrapper<T>.baz(transform: (T) -> Unit): T = TODO()
|
||||
|
||||
fun test2() {
|
||||
takeFun<String>(<!UNSUPPORTED_FEATURE!>::foo<!>)
|
||||
|
||||
callFun<String, Wrapper<String>>(<!UNSUPPORTED_FEATURE!>::createWrapper<!>)
|
||||
callFun<Int, Wrapper<Number>>(<!UNSUPPORTED_FEATURE!>::createWrapper<!>)
|
||||
callFun<String, Wrapper<*>>(<!UNSUPPORTED_FEATURE!>::createWrapper<!>)
|
||||
|
||||
callFun<Int, Wrapper<Int>>(<!UNSUPPORTED_FEATURE!>::createWrapper<!>).baz(<!UNSUPPORTED_FEATURE!>::foo<!>)
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
fun test3() {
|
||||
val a1: Array<Double.(Double) -> Double> = arrayOf(Double::plus, Double::minus)
|
||||
val a2: Array<Double.(Int) -> Double> = arrayOf(Double::plus, Double::minus)
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
class A1 {
|
||||
fun <T> a1(t: T): Unit {}
|
||||
fun test1(): (String) -> Unit = A1()::a1
|
||||
}
|
||||
|
||||
class A2 {
|
||||
fun <K, V> a2(key: K): V = TODO()
|
||||
|
||||
fun test1(): (String) -> Unit = A2()::a2
|
||||
fun <T3> test2(): (T3) -> T3 = A2()::a2
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
fun foo1(x: Int?) {}
|
||||
fun foo1(y: String?) {}
|
||||
fun foo1(z: Boolean) {}
|
||||
|
||||
fun <T> baz1(element: (T) -> Unit): T? = null
|
||||
|
||||
fun test4() {
|
||||
val a1: Int? = baz1(::foo1)
|
||||
val a2: String? = baz1(::foo1)
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T> bar(/*0*/ s: T): kotlin.Unit
|
||||
public fun </*0*/ T> baz1(/*0*/ element: (T) -> kotlin.Unit): T?
|
||||
public fun </*0*/ T, /*1*/ R> callFun(/*0*/ f: (T) -> R): R
|
||||
public fun </*0*/ T> complex(/*0*/ t: T, /*1*/ f: (T) -> kotlin.Unit): kotlin.Unit
|
||||
public fun </*0*/ T, /*1*/ R : Wrapper<in T>> createWrapper(/*0*/ s: T): R
|
||||
public fun </*0*/ T> foo(/*0*/ s: T): kotlin.Unit
|
||||
public fun foo1(/*0*/ z: kotlin.Boolean): kotlin.Unit
|
||||
public fun foo1(/*0*/ x: kotlin.Int?): kotlin.Unit
|
||||
public fun foo1(/*0*/ y: kotlin.String?): kotlin.Unit
|
||||
public fun </*0*/ T> simple(/*0*/ f: (T) -> kotlin.Unit): kotlin.Unit
|
||||
public fun </*0*/ T> takeFun(/*0*/ f: (T) -> kotlin.Unit): kotlin.Unit
|
||||
public fun test1(): kotlin.Unit
|
||||
public fun test2(): kotlin.Unit
|
||||
public fun test3(): kotlin.Unit
|
||||
public fun test4(): kotlin.Unit
|
||||
public fun </*0*/ T> Wrapper<T>.baz(/*0*/ transform: (T) -> kotlin.Unit): T
|
||||
|
||||
public final class A1 {
|
||||
public constructor A1()
|
||||
public final fun </*0*/ T> a1(/*0*/ t: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun test1(): (kotlin.String) -> kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class A2 {
|
||||
public constructor A2()
|
||||
public final fun </*0*/ K, /*1*/ V> a2(/*0*/ key: K): V
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun test1(): (kotlin.String) -> kotlin.Unit
|
||||
public final fun </*0*/ T3> test2(): (T3) -> T3
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class Wrapper</*0*/ T> {
|
||||
public constructor Wrapper</*0*/ T>(/*0*/ value: T)
|
||||
public final val value: T
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -2298,6 +2298,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noInferenceFeatureForCallableReferences.kt")
|
||||
public void testNoInferenceFeatureForCallableReferences() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/generic/noInferenceFeatureForCallableReferences.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("resolutionGenericCallableWithNullableTypes.kt")
|
||||
public void testResolutionGenericCallableWithNullableTypes() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/generic/resolutionGenericCallableWithNullableTypes.kt");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,6 +40,7 @@ enum class LanguageFeature(val sinceVersion: LanguageVersion?, val hintUrl: Stri
|
||||
ShortSyntaxForPropertyGetters(KOTLIN_1_1),
|
||||
RefinedSamAdaptersPriority(KOTLIN_1_1),
|
||||
SafeCallBoundSmartCasts(KOTLIN_1_1),
|
||||
TypeInferenceOnGenericsForCallableReferences(KOTLIN_1_1),
|
||||
|
||||
// Experimental features
|
||||
MultiPlatformProjects(null, "https://kotlinlang.org/docs/diagnostics/experimental-multitraget-projects"),
|
||||
|
||||
Reference in New Issue
Block a user