diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 41705d62d4f..ec1c9a5ed18 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -272,35 +272,6 @@ fun isSubtypeForTypeMismatch(context: ConeInferenceContext, subtype: ConeKotlinT val subtypeFullyExpanded = subtype.fullyExpandedType(context.session) val supertypeFullyExpanded = supertype.fullyExpandedType(context.session) return AbstractTypeChecker.isSubtypeOf(context, subtypeFullyExpanded, supertypeFullyExpanded) - || isSubtypeOfForFunctionalTypeReturningUnit(context.session.typeContext, subtypeFullyExpanded, supertypeFullyExpanded) -} - -private fun isSubtypeOfForFunctionalTypeReturningUnit( - context: ConeInferenceContext, - subtype: ConeKotlinType, - supertype: ConeKotlinType -): Boolean { - if (!supertype.isBuiltinFunctionalType(context.session)) return false - val functionalTypeReturnType = supertype.typeArguments.lastOrNull() - if ((functionalTypeReturnType as? ConeClassLikeType)?.isUnit == true) { - // We don't try to match return type for this case - // Dropping the return type (getting only the lambda args) - val superTypeArgs = supertype.typeArguments.dropLast(1) - val subTypeArgs = subtype.typeArguments.dropLast(1) - if (superTypeArgs.size != subTypeArgs.size) return false - - for (i in superTypeArgs.indices) { - val subTypeArg = subTypeArgs[i].type ?: return false - val superTypeArg = superTypeArgs[i].type ?: return false - - if (!AbstractTypeChecker.isSubtypeOf(context.session.typeContext, subTypeArg, superTypeArg)) { - return false - } - } - - return true - } - return false } fun FirCallableDeclaration.isVisibleInClass(parentClass: FirClass): Boolean { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/CopyUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/CopyUtils.kt index b82bb2f4440..b2e493138ef 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/CopyUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/CopyUtils.kt @@ -54,6 +54,11 @@ fun FirTypeRef.resolvedTypeFromPrototype( buildResolvedTypeRef { source = this@resolvedTypeFromPrototype.source this.type = type + delegatedTypeRef = when (val original = this@resolvedTypeFromPrototype) { + is FirResolvedTypeRef -> original.delegatedTypeRef + is FirUserTypeRef -> original + else -> null + } annotations += this@resolvedTypeFromPrototype.annotations } } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/InferenceUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/InferenceUtils.kt index df84e33e04e..5de539a5391 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/InferenceUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/InferenceUtils.kt @@ -79,6 +79,11 @@ fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean { return isFunctionalType(session) { it == FunctionClassKind.Function } } +// Function, SuspendFunction +fun ConeKotlinType.isFunctionalOrSuspendFunctionalType(session: FirSession): Boolean { + return isFunctionalType(session) { it == FunctionClassKind.Function || it == FunctionClassKind.SuspendFunction } +} + // SuspendFunction, KSuspendFunction fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean { return isFunctionalType(session) { it.isSuspendType } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index a07e6ccf020..6c67a5adfa7 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -25,8 +25,7 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.impl.* -import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef -import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.builder.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible @@ -426,15 +425,15 @@ private fun ConeKotlinType.approximateToOnlySupertype(session: FirSession): Cone } fun shouldApproximateLocalTypesOfNonLocalDeclaration(containingCallableVisibility: Visibility?, isInlineFunction: Boolean): Boolean { - if (containingCallableVisibility == null) { - return false - } // Approximate types for non-private (all but package private or private) members. // Also private inline functions, as per KT-33917. - return containingCallableVisibility == Visibilities.Public || - containingCallableVisibility == Visibilities.Protected || - containingCallableVisibility == Visibilities.Internal || - containingCallableVisibility == Visibilities.Private && isInlineFunction + return when (containingCallableVisibility) { + Visibilities.Public, + Visibilities.Protected, + Visibilities.Internal -> true + Visibilities.Private -> isInlineFunction + else -> false + } } fun FirDeclaration.visibilityForApproximation(container: FirDeclaration?): Visibility { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index 6fc182b5733..b546e12947c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildStarProjection import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl +import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.transformSingle @@ -635,8 +636,10 @@ class FirCallCompletionResultsWriterTransformer( } if (finalType != null) { - val resultType = anonymousFunction.returnTypeRef.withReplacedConeType(finalType) - anonymousFunction.transformReturnTypeRef(StoreType, resultType) + if (anonymousFunction.returnTypeRef !is FirImplicitUnitTypeRef) { + val resultType = anonymousFunction.returnTypeRef.withReplacedConeType(finalType) + anonymousFunction.transformReturnTypeRef(StoreType, resultType) + } needUpdateLambdaType = true } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 4e0278a6d47..2d3394b0f15 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -876,9 +876,10 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve initialReturnTypeRef is FirResolvedTypeRef -> { initialReturnTypeRef.coneType } - implicitReturns.isNotEmpty() || lambda.returnType?.isUnit == true -> { + implicitReturns.isNotEmpty() || (lambda.returnType?.isUnit == true && lambda.isLambda) -> { // i.e., early return, e.g., l@{ ... return@l ... } // Note that the last statement will be coerced to Unit if needed. + // also we don't coerce to Unit anonymous functions, only lambdas session.builtinTypes.unitType.type } else -> { @@ -888,11 +889,13 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve ) ?: session.builtinTypes.unitType.type } } - lambda.replaceReturnTypeRef( - lambda.returnTypeRef.resolvedTypeFromPrototype(returnType).also { - session.lookupTracker?.recordTypeResolveAsLookup(it, lambda.source, components.file.source) - } - ) + if (lambda.returnTypeRef !is FirImplicitUnitTypeRef) { + lambda.replaceReturnTypeRef( + initialReturnTypeRef.resolvedTypeFromPrototype(returnType).also { + session.lookupTracker?.recordTypeResolveAsLookup(it, lambda.source, components.file.source) + } + ) + } lambda.replaceTypeRef( lambda.constructFunctionalTypeRef( isSuspend = expectedTypeRef.coneTypeSafe()?.isSuspendFunctionType(session) == true diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt index 7e93bdab7e6..5bd00c8707f 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt @@ -10,7 +10,7 @@ fun unitUnitReturn() : Unit {return Unit} fun test1() : Any = {return} fun test2() : Any = a@ {return@a 1} fun test3() : Any { return } -fun test4(): ()-> Unit = { return@test4 } +fun test4(): ()-> Unit = { return@test4 } fun test5(): Any = l@{ return@l } fun test6(): Any = {return 1} diff --git a/compiler/testData/diagnostics/tests/functionLiterals/missedTypeMismatch.fir.kt b/compiler/testData/diagnostics/tests/functionLiterals/missedTypeMismatch.fir.kt index d5fe7f45e5b..34ea4c2f459 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/missedTypeMismatch.fir.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/missedTypeMismatch.fir.kt @@ -11,8 +11,8 @@ fun main() { val a0: () -> Int = fun(): String = "1" val a1: () -> Int = (fun() = "1") - val a2: () -> Unit = (fun() = "1") - val a3: Unit = (fun() = "1") + val a2: () -> Unit = (fun() = "1") + val a3: Unit = (fun() = "1") val a4 = (fun() = "1") val a5 = (fun(): String = "1") val a6: () -> Int = (fun() = 1) @@ -36,5 +36,5 @@ fun main() { val a18: () -> Int = fun() {} val a19: () -> () -> Int = fun() = fun() {} val a20: () -> () -> () -> Unit = fun() = fun() = {} - val a21: () -> () -> () -> Int = fun() = fun() = {} + val a21: () -> () -> () -> Int = fun() = fun() = {} } diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt new file mode 100644 index 00000000000..ca0d9acc14c --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.fir.kt @@ -0,0 +1,11 @@ +class Foo(val baz: Baz) + +class Bar { + val foo: Foo<*> = TODO() + + fun bar(): Baz { + return foo.baz + } +} + +typealias Baz = (@UnsafeVariance T) -> Unit diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt index 708a7a96125..05ad642e149 100644 --- a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL class Foo(val baz: Baz) class Bar { diff --git a/compiler/testData/diagnostics/tests/regressions/kt352.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt352.fir.kt index 35c388d0c42..016ff859f2e 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt352.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt352.fir.kt @@ -14,7 +14,7 @@ class A() { //more tests val g : () -> Unit = { 42 } -val gFunction : () -> Unit = fun(): Int = 1 +val gFunction : () -> Unit = fun(): Int = 1 val h : () -> Unit = { doSmth() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/suspendFunctions.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/suspendFunctions.fir.kt index 3e542ed53d1..7d960f86839 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/suspendFunctions.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/suspendFunctions.fir.kt @@ -19,7 +19,7 @@ fun main() { val x1: suspend (Int) -> Unit = takeSuspend(")!>id { it }, ")!>{ x -> x }) // Here, the error should be - val x2: (Int) -> Unit = takeSuspend(")!>id { it }, ")!>{ x -> x }) + val x2: (Int) -> Unit = takeSuspend(")!>id { it }, ")!>{ x -> x }) val x3: suspend (Int) -> Unit = takeSimpleFunction(")!>id { it }, ")!>{ x -> x }) val x4: (Int) -> Unit = takeSimpleFunction(id Unit> {}, ")!>{}) }