FIR: allow fun T.() = ... as an instance of (T) -> ...
It was already done by the previous commit by mistake, but it broke if there are other value parameters because the type of the first parameter would be inferred to be same as the type of the receiver.
This commit is contained in:
+1
@@ -477,6 +477,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
parameter<ConeKotlinType>("varargParameterType")
|
||||
}
|
||||
val VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION by error<FirSourceElement, KtParameter>()
|
||||
val CANNOT_INFER_PARAMETER_TYPE by error<FirSourceElement, KtParameter>()
|
||||
}
|
||||
|
||||
val FUN_INTERFACES by object : DiagnosticGroup("Fun interfaces") {
|
||||
|
||||
@@ -295,6 +295,7 @@ object FirErrors {
|
||||
val MULTIPLE_VARARG_PARAMETERS by error0<FirSourceElement, KtParameter>(SourceElementPositioningStrategies.PARAMETER_VARARG_MODIFIER)
|
||||
val FORBIDDEN_VARARG_PARAMETER_TYPE by error1<FirSourceElement, KtParameter, ConeKotlinType>(SourceElementPositioningStrategies.PARAMETER_VARARG_MODIFIER)
|
||||
val VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION by error0<FirSourceElement, KtParameter>()
|
||||
val CANNOT_INFER_PARAMETER_TYPE by error0<FirSourceElement, KtParameter>()
|
||||
|
||||
// Fun interfaces
|
||||
val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+2
@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.BREAK_OR_CONTINUE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_CHANGE_ACCESS_PRIVILEGE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_INFER_PARAMETER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_VAL
|
||||
@@ -685,6 +686,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
map.put(MULTIPLE_VARARG_PARAMETERS, "Multiple vararg-parameters are prohibited")
|
||||
map.put(FORBIDDEN_VARARG_PARAMETER_TYPE, "Forbidden vararg parameter type: {0}", RENDER_TYPE)
|
||||
map.put(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION, "A type annotation is required on a value parameter")
|
||||
map.put(CANNOT_INFER_PARAMETER_TYPE, "cannot infer a type for this parameter. Please specify it explicitly.")
|
||||
|
||||
// Fun interfaces
|
||||
map.put(FUN_INTERFACE_CONSTRUCTOR_REFERENCE, "Functional interface constructor references are prohibited")
|
||||
|
||||
+1
@@ -176,6 +176,7 @@ private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<FirSourceEl
|
||||
DiagnosticKind.NotLoopLabel -> FirErrors.NOT_A_LOOP_LABEL
|
||||
DiagnosticKind.VariableExpected -> FirErrors.VARIABLE_EXPECTED
|
||||
DiagnosticKind.ValueParameterWithNoTypeAnnotation -> FirErrors.VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION
|
||||
DiagnosticKind.CannotInferParameterType -> FirErrors.CANNOT_INFER_PARAMETER_TYPE
|
||||
DiagnosticKind.UnknownCallableKind -> FirErrors.UNKNOWN_CALLABLE_KIND
|
||||
DiagnosticKind.IllegalProjectionUsage -> FirErrors.ILLEGAL_PROJECTION_USAGE
|
||||
DiagnosticKind.MissingStdlibClass -> FirErrors.MISSING_STDLIB_CLASS
|
||||
|
||||
+14
-16
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
@@ -201,30 +203,25 @@ fun ConeKotlinType.isKClassType(): Boolean {
|
||||
return classId == StandardClassIds.KClass
|
||||
}
|
||||
|
||||
private fun ConeTypeProjection.typeOrDefault(default: ConeKotlinType): ConeKotlinType =
|
||||
when (this) {
|
||||
is ConeKotlinTypeProjection -> type
|
||||
is ConeStarProjection -> default
|
||||
}
|
||||
|
||||
fun ConeKotlinType.receiverType(session: FirSession): ConeKotlinType? {
|
||||
if (!isBuiltinFunctionalType(session) || !isExtensionFunctionType(session)) return null
|
||||
return when (val projection = fullyExpandedType(session).typeArguments.first()) {
|
||||
is ConeKotlinTypeProjection -> projection.type
|
||||
is ConeStarProjection -> session.builtinTypes.nothingType.type
|
||||
}
|
||||
return fullyExpandedType(session).typeArguments.first().typeOrDefault(session.builtinTypes.nothingType.type)
|
||||
}
|
||||
|
||||
fun ConeKotlinType.returnType(session: FirSession): ConeKotlinType {
|
||||
require(this is ConeClassLikeType)
|
||||
return when (val projection = fullyExpandedType(session).typeArguments.last()) {
|
||||
is ConeKotlinTypeProjection -> projection.type
|
||||
is ConeStarProjection -> session.builtinTypes.nullableAnyType.type
|
||||
}
|
||||
return fullyExpandedType(session).typeArguments.last().typeOrDefault(session.builtinTypes.nullableAnyType.type)
|
||||
}
|
||||
|
||||
fun ConeKotlinType.valueParameterTypesIncludingReceiver(session: FirSession): List<ConeKotlinType> {
|
||||
require(this is ConeClassLikeType)
|
||||
return fullyExpandedType(session).typeArguments.dropLast(1).map {
|
||||
when (it) {
|
||||
is ConeKotlinTypeProjection -> it.type
|
||||
is ConeStarProjection -> session.builtinTypes.nothingType.type
|
||||
}
|
||||
}
|
||||
return fullyExpandedType(session).typeArguments.dropLast(1).map { it.typeOrDefault(session.builtinTypes.nothingType.type) }
|
||||
}
|
||||
|
||||
val FirAnonymousFunction.returnType: ConeKotlinType? get() = returnTypeRef.coneTypeSafe()
|
||||
@@ -261,7 +258,7 @@ fun extractLambdaInfoFromFunctionalType(
|
||||
session.builtinTypes.unitType.type
|
||||
else
|
||||
argument.returnType ?: expectedType.returnType(session)
|
||||
// `fun (x: T) = ...` and `fun T.() = ...` are both instances of `T.() -> V`; `fun () = ...` is not.
|
||||
// `fun (x: T) = ...` and `fun T.() = ...` are both instances of `T.() -> V` and `(T) -> V`; `fun () = ...` is not.
|
||||
// For lambdas, the existence of the receiver is always implied by the expected type, and a value parameter
|
||||
// can never fill its role.
|
||||
val receiverType = if (argument.isLambda) expectedType.receiverType(session) else argument.receiverType
|
||||
@@ -272,7 +269,8 @@ fun extractLambdaInfoFromFunctionalType(
|
||||
expectedParameters // Infer existence of a parameter named `it` of an appropriate type.
|
||||
} else {
|
||||
argument.valueParameters.mapIndexed { index, parameter ->
|
||||
parameter.returnTypeRef.coneTypeSafe() ?: expectedParameters.getOrNull(index) ?: session.builtinTypes.nothingType.type
|
||||
parameter.returnTypeRef.coneTypeSafe() ?: expectedParameters.getOrNull(index)
|
||||
?: ConeClassErrorType(ConeSimpleDiagnostic("Cannot infer type for parameter ${parameter.name}", DiagnosticKind.CannotInferParameterType))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ enum class DiagnosticKind {
|
||||
Java,
|
||||
SuperNotAllowed,
|
||||
ValueParameterWithNoTypeAnnotation,
|
||||
CannotInferParameterType,
|
||||
UnknownCallableKind,
|
||||
IllegalProjectionUsage,
|
||||
MissingStdlibClass,
|
||||
|
||||
+6
@@ -1338,6 +1338,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CANNOT_INFER_PARAMETER_TYPE) { firDiagnostic ->
|
||||
CannotInferParameterTypeImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.FUN_INTERFACE_CONSTRUCTOR_REFERENCE) { firDiagnostic ->
|
||||
FunInterfaceConstructorReferenceImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
|
||||
+4
@@ -949,6 +949,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = ValueParameterWithNoTypeAnnotation::class
|
||||
}
|
||||
|
||||
abstract class CannotInferParameterType : KtFirDiagnostic<KtParameter>() {
|
||||
override val diagnosticClass get() = CannotInferParameterType::class
|
||||
}
|
||||
|
||||
abstract class FunInterfaceConstructorReference : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = FunInterfaceConstructorReference::class
|
||||
}
|
||||
|
||||
+7
@@ -1529,6 +1529,13 @@ internal class ValueParameterWithNoTypeAnnotationImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class CannotInferParameterTypeImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.CannotInferParameterType(), KtAbstractFirDiagnostic<KtParameter> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class FunInterfaceConstructorReferenceImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
|
||||
Reference in New Issue
Block a user