Prohibit adapted reference resolve against reflective types

There are design questions about reflection for adapted references,
 so the current proposal is to prohibit reflection on them and support
 it properly later

 #KT-40406 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2020-07-17 08:45:17 +03:00
parent d8de37f665
commit 0c79de1a98
18 changed files with 258 additions and 5 deletions
@@ -228,6 +228,12 @@ class CallableReferencesCandidateFactory(
markCandidateForCompatibilityResolve(diagnostics)
}
if (callableReferenceAdaptation != null && expectedType != null && hasNonTrivialAdaptation(callableReferenceAdaptation)) {
if (!expectedType.isFunctionType && !expectedType.isSuspendFunctionType) { // expectedType has some reflection type
diagnostics.add(AdaptedCallableReferenceIsUsedWithReflection(argument))
}
}
if (callableReferenceAdaptation != null &&
callableReferenceAdaptation.defaults != 0 &&
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType)
@@ -278,11 +284,14 @@ class CallableReferencesCandidateFactory(
if (callableReferenceAdaptation == null) return false
return callableReferenceAdaptation.defaults != 0 ||
return hasNonTrivialAdaptation(callableReferenceAdaptation)
}
private fun hasNonTrivialAdaptation(callableReferenceAdaptation: CallableReferenceAdaptation) =
callableReferenceAdaptation.defaults != 0 ||
callableReferenceAdaptation.suspendConversionStrategy != SuspendConversionStrategy.NO_CONVERSION ||
callableReferenceAdaptation.coercionStrategy != CoercionStrategy.NO_COERCION ||
callableReferenceAdaptation.mappedArguments.values.any { it is ResolvedCallArgument.VarargArgument }
}
private enum class VarargMappingState {
UNMAPPED, MAPPED_WITH_PLAIN_ARGS, MAPPED_WITH_ARRAY
@@ -296,6 +305,11 @@ class CallableReferencesCandidateFactory(
): CallableReferenceAdaptation? {
if (callComponents.languageVersionSettings.apiVersion < ApiVersion.KOTLIN_1_4) return null
if (expectedType == null) return null
// Do not adapt references against KCallable type as it's impossible to map defaults/vararg to absent parameters of KCallable
if (ReflectionTypes.hasKCallableTypeFqName(expectedType)) return null
val inputOutputTypes = extractInputOutputTypesFromCallableReferenceExpectedType(expectedType) ?: return null
val expectedArgumentCount = inputOutputTypes.inputTypes.size - unboundReceiverCount
@@ -263,4 +263,13 @@ class CompatibilityWarningOnArgument(
override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(argument, this)
}
}
class AdaptedCallableReferenceIsUsedWithReflection(
val argument: CallableReferenceKotlinCallArgument,
) : KotlinCallDiagnostic(RESOLVED_WITH_ERROR) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(argument, this)
}
}