FIR: no constraint for coerced-to-Unit last expression of lambda
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
4ab0897d7d
commit
6239301f4e
+2
-2
@@ -59,7 +59,7 @@ FILE: RedundantReturnUnitTypeChecker.kt
|
||||
}
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
^foo this@R|/B|.R|/B.run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| {
|
||||
^foo this@R|/B|.R|/B.run|<R|kotlin/Unit|>(<L> = run@fun <anonymous>(): R|kotlin/Unit| {
|
||||
this@R|/B|.R|/B.bar|()
|
||||
}
|
||||
)
|
||||
@@ -88,7 +88,7 @@ FILE: RedundantReturnUnitTypeChecker.kt
|
||||
}
|
||||
|
||||
public final fun goo(): R|kotlin/Unit| {
|
||||
^goo (this@R|/B|, Int(1)).R|/B.let|<R|kotlin/Int|, R|kotlin/Int|>(<L> = let@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Int| {
|
||||
^goo (this@R|/B|, Int(1)).R|/B.let|<R|kotlin/Int|, R|kotlin/Unit|>(<L> = let@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
this@R|/B|.R|/B.bar|()
|
||||
}
|
||||
)
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ digraph complexPostponedCfg_kt {
|
||||
}
|
||||
34 [label="Call arguments union" style="filled" fillcolor=yellow];
|
||||
35 [label="Postponed exit from lambda"];
|
||||
36 [label="Function call: R|kotlin/with|<R|FirFunctionCall|, R|kotlin/Boolean|>(...)"];
|
||||
36 [label="Function call: R|kotlin/with|<R|FirFunctionCall|, R|kotlin/Unit|>(...)"];
|
||||
37 [label="Exit block"];
|
||||
}
|
||||
38 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ FILE: complexPostponedCfg.kt
|
||||
lval firstCalls: R|kotlin/collections/List<FirFunctionCall>| = R|kotlin/with|<R|FirFunctionCall|, R|kotlin/collections/List<FirFunctionCall>|>((R|<local>/statements|.R|kotlin/collections/last|<R|FirBase|>() as R|FirFunctionCall|), <L> = setCall@fun R|FirFunctionCall|.<anonymous>(): R|kotlin/collections/List<FirFunctionCall>| <kind=EXACTLY_ONCE> {
|
||||
^ R|kotlin/collections/buildList|<R|FirFunctionCall|>(<L> = buildList@fun R|kotlin/collections/MutableList<FirFunctionCall>|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
this@R|special/anonymous|.R|SubstitutionOverride<kotlin/collections/MutableList.add: R|kotlin/Boolean|>|(this@R|special/anonymous|)
|
||||
R|kotlin/with|<R|FirFunctionCall|, R|kotlin/Boolean|>((R|<local>/arguments|.R|kotlin/collections/last|<R|FirBase|>() as R|FirFunctionCall|), <L> = plusCall@fun R|FirFunctionCall|.<anonymous>(): R|kotlin/Boolean| <kind=EXACTLY_ONCE> {
|
||||
R|kotlin/with|<R|FirFunctionCall|, R|kotlin/Unit|>((R|<local>/arguments|.R|kotlin/collections/last|<R|FirBase|>() as R|FirFunctionCall|), <L> = plusCall@fun R|FirFunctionCall|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
this@R|special/anonymous|.R|SubstitutionOverride<kotlin/collections/MutableList.add: R|kotlin/Boolean|>|(this@R|special/anonymous|)
|
||||
this@R|special/anonymous|.R|SubstitutionOverride<kotlin/collections/MutableList.add: R|kotlin/Boolean|>|((R|<local>/explicitReceiver| as R|FirFunctionCall|))
|
||||
}
|
||||
|
||||
+21
-11
@@ -130,7 +130,7 @@ class PostponedArgumentsAnalyzer(
|
||||
rawReturnType,
|
||||
stubsForPostponedVariables
|
||||
)
|
||||
applyResultsOfAnalyzedLambdaToCandidateSystem(c, lambda, candidate, results, ::substitute)
|
||||
applyResultsOfAnalyzedLambdaToCandidateSystem(c, lambda, candidate, results, expectedTypeForReturnArguments, ::substitute)
|
||||
return results
|
||||
}
|
||||
|
||||
@@ -139,6 +139,7 @@ class PostponedArgumentsAnalyzer(
|
||||
lambda: ResolvedLambdaAtom,
|
||||
candidate: Candidate,
|
||||
results: ReturnArgumentsAnalysisResult,
|
||||
expectedReturnType: ConeKotlinType? = null,
|
||||
substitute: (ConeKotlinType) -> ConeKotlinType = c.createSubstituteFunctorForLambdaAnalysis()
|
||||
) {
|
||||
val (returnArguments, inferenceSession) = results
|
||||
@@ -164,21 +165,30 @@ class PostponedArgumentsAnalyzer(
|
||||
|
||||
val checkerSink: CheckerSink = CheckerSinkImpl(candidate)
|
||||
|
||||
val lastExpression = lambda.atom.body?.statements?.lastOrNull() as? FirExpression
|
||||
var hasExpressionInReturnArguments = false
|
||||
// No constraint for return expressions of lambda if it has Unit return type.
|
||||
val lambdaReturnType = lambda.returnType.let(substitute).takeUnless { it.isUnit }
|
||||
returnArguments.forEach {
|
||||
if (it !is FirExpression) return@forEach
|
||||
hasExpressionInReturnArguments = true
|
||||
candidate.resolveArgumentExpression(
|
||||
c.getBuilder(),
|
||||
it,
|
||||
lambdaReturnType,
|
||||
lambda.atom.returnTypeRef, // TODO: proper ref
|
||||
checkerSink,
|
||||
context = resolutionContext,
|
||||
isReceiver = false,
|
||||
isDispatch = false
|
||||
)
|
||||
// If it is the last expression, and the expected type is Unit, that expression will be coerced to Unit.
|
||||
// If the last expression is of Unit type, of course it's not coercion-to-Unit case.
|
||||
val lastExpressionCoercedToUnit =
|
||||
it == lastExpression && expectedReturnType?.isUnit == true && !it.typeRef.coneType.isUnit
|
||||
// No constraint for the last expression of lambda if it will be coerced to Unit.
|
||||
if (!lastExpressionCoercedToUnit) {
|
||||
candidate.resolveArgumentExpression(
|
||||
c.getBuilder(),
|
||||
it,
|
||||
lambdaReturnType,
|
||||
lambda.atom.returnTypeRef, // TODO: proper ref
|
||||
checkerSink,
|
||||
context = resolutionContext,
|
||||
isReceiver = false,
|
||||
isDispatch = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasExpressionInReturnArguments && lambdaReturnType != null) {
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// FILE: TestJ.java
|
||||
|
||||
Vendored
+2
-2
@@ -142,8 +142,8 @@ fun main() {
|
||||
val x18: (C) -> Unit = select(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, id<(B) -> Unit> { x -> x })
|
||||
|
||||
// Resolution of extension/non-extension functions combination
|
||||
val x19: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.String>")!>id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>this<!> }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
val x20: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.String>")!>{ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>this<!> }<!>, (fun(x: String) {}))
|
||||
val x19: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>this<!> }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
val x20: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>{ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>this<!> }<!>, (fun(x: String) {}))
|
||||
val x21: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
select(id<String.() -> Unit>(fun(x: String) {}), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.String, kotlin.String, kotlin.Unit>")!>id(fun String.(x: String) {})<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.String, kotlin.String, kotlin.Unit>")!>id(fun(x: String, y: String) {})<!>)
|
||||
|
||||
+4
-4
@@ -14,12 +14,12 @@ fun main() {
|
||||
select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction0<kotlin.Unit>")!>id {}<!>, id(suspend {}))
|
||||
select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction0<kotlin.Unit>")!>id {}<!>, id<suspend () -> Unit> {})
|
||||
|
||||
takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Int>")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Int>")!>{ x -> x }<!>)
|
||||
takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>{ x -> x }<!>)
|
||||
|
||||
val x1: suspend (Int) -> Unit = takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Int>")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Int>")!>{ x -> x }<!>)
|
||||
val x1: suspend (Int) -> Unit = takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>{ x -> x }<!>)
|
||||
|
||||
// Here, the error should be
|
||||
val x2: (Int) -> Unit = takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Int>")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Int>")!>{ x -> x }<!>)
|
||||
val x3: suspend (Int) -> Unit = takeSimpleFunction(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Int>")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Int>")!>{ x -> x }<!>)
|
||||
val x2: (Int) -> Unit = takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>{ x -> x }<!>)
|
||||
val x3: suspend (Int) -> Unit = takeSimpleFunction(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.coroutines.SuspendFunction1<kotlin.Int, kotlin.Unit>")!>{ x -> x }<!>)
|
||||
val x4: (Int) -> Unit = <!INAPPLICABLE_CANDIDATE!>takeSimpleFunction<!>(id<suspend (Int) -> Unit> {}, <!DEBUG_INFO_EXPRESSION_TYPE("Type is unknown")!>{}<!>)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user