[FIR] Fix lambda resolve in independent context

This commit is contained in:
Mikhail Glukhikh
2020-02-04 10:14:34 +03:00
parent 4f8d0382f7
commit 64c7ab1302
19 changed files with 75 additions and 62 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirTransformer
@@ -410,8 +411,9 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
is ResolutionMode.LambdaResolution -> { is ResolutionMode.LambdaResolution -> {
transformAnonymousFunctionWithLambdaResolution(anonymousFunction, data).compose() transformAnonymousFunctionWithLambdaResolution(anonymousFunction, data).compose()
} }
is ResolutionMode.WithExpectedType -> { is ResolutionMode.WithExpectedType, is ResolutionMode.ContextIndependent -> {
val resolvedLambdaAtom = (data.expectedTypeRef as? FirResolvedTypeRef)?.let { val expectedTypeRef = (data as? ResolutionMode.WithExpectedType)?.expectedTypeRef ?: FirImplicitTypeRefImpl(null)
val resolvedLambdaAtom = (expectedTypeRef as? FirResolvedTypeRef)?.let {
extractLambdaInfoFromFunctionalType( extractLambdaInfoFromFunctionalType(
it.type, it, anonymousFunction it.type, it, anonymousFunction
) )
@@ -467,7 +469,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
?: af.returnTypeRef ?: af.returnTypeRef
) )
af = af.transformValueParameters(ImplicitToErrorTypeTransformer, null) af = af.transformValueParameters(ImplicitToErrorTypeTransformer, null)
val bodyExpectedType = returnTypeRefFromResolvedAtom ?: data.expectedTypeRef val bodyExpectedType = returnTypeRefFromResolvedAtom ?: expectedTypeRef
af = transformFunction(af, withExpectedType(bodyExpectedType)).single as FirAnonymousFunction af = transformFunction(af, withExpectedType(bodyExpectedType)).single as FirAnonymousFunction
// To separate function and separate commit // To separate function and separate commit
val writer = FirCallCompletionResultsWriterTransformer( val writer = FirCallCompletionResultsWriterTransformer(
@@ -478,15 +480,12 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
integerOperatorsTypeUpdater, integerOperatorsTypeUpdater,
integerLiteralTypeApproximator integerLiteralTypeApproximator
) )
af.transformSingle(writer, data.expectedTypeRef.coneTypeSafe<ConeKotlinType>()?.toExpectedType()) af.transformSingle(writer, expectedTypeRef.coneTypeSafe<ConeKotlinType>()?.toExpectedType())
val returnTypes = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(af).mapNotNull { (it as? FirExpression)?.resultType?.coneTypeUnsafe() } val returnTypes = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(af).mapNotNull { (it as? FirExpression)?.resultType?.coneTypeUnsafe() }
af.replaceReturnTypeRef(af.returnTypeRef.resolvedTypeFromPrototype(inferenceComponents.ctx.commonSuperTypeOrNull(returnTypes) ?: session.builtinTypes.unitType.coneTypeUnsafe())) af.replaceReturnTypeRef(af.returnTypeRef.resolvedTypeFromPrototype(inferenceComponents.ctx.commonSuperTypeOrNull(returnTypes) ?: session.builtinTypes.unitType.coneTypeUnsafe()))
af.replaceTypeRef(af.constructFunctionalTypeRef(session)) af.replaceTypeRef(af.constructFunctionalTypeRef(session))
af.compose() af.compose()
} }
ResolutionMode.ContextIndependent -> {
transformFunction(anonymousFunction, data)
}
is ResolutionMode.WithStatus -> { is ResolutionMode.WithStatus -> {
throw AssertionError("Should not be here in WithStatus mode") throw AssertionError("Should not be here in WithStatus mode")
} }
@@ -8,5 +8,10 @@ fun main() {
bar { "This is also test" } bar { "This is also test" }
itIs { "this is $it test" } itIs { "this is $it test" }
multipleArgs { a, b -> "This is test of $a, $b" } multipleArgs { a, b -> "This is test of $a, $b" }
val s = { "OK" }()
val f = { "OK" }
val ss = f.invoke()
} }
@@ -24,4 +24,13 @@ FILE: lambda.kt
<strcat>(String(This is test of ), R|<local>/a|.R|kotlin/Any.toString|(), String(, ), R|<local>/b|.R|kotlin/Any.toString|()) <strcat>(String(This is test of ), R|<local>/a|.R|kotlin/Any.toString|(), String(, ), R|<local>/b|.R|kotlin/Any.toString|())
} }
) )
lval s: R|kotlin/String| = fun <anonymous>(): R|kotlin/String| {
String(OK)
}
.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
lval f: R|() -> kotlin/String| = fun <anonymous>(): R|kotlin/String| {
String(OK)
}
lval ss: R|kotlin/String| = R|<local>/f|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
} }
@@ -56,10 +56,10 @@ fun f() : Int.() -> Unit = {}
fun main1() { fun main1() {
1.<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!>; 1.<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!>;
<!UNRESOLVED_REFERENCE!>{1}()<!>; {1}();
<!UNRESOLVED_REFERENCE!>(fun (x : Int) = x)(1)<!> (fun (x : Int) = x)(1)
1.<!UNRESOLVED_REFERENCE!>(fun Int.(x : Int) = x)(1)<!>; 1.<!UNRESOLVED_REFERENCE!>(fun Int.(x : Int) = x)(1)<!>;
l@<!UNRESOLVED_REFERENCE!>{1}()<!> l@{1}()
1.<!UNRESOLVED_REFERENCE!>((fun Int.() = 1))()<!> 1.<!UNRESOLVED_REFERENCE!>((fun Int.() = 1))()<!>
1.<!UNRESOLVED_REFERENCE!>(f())()<!> 1.<!UNRESOLVED_REFERENCE!>(f())()<!>
1.<!UNRESOLVED_REFERENCE!>if(true){f()}else{f()}()<!> 1.<!UNRESOLVED_REFERENCE!>if(true){f()}else{f()}()<!>
@@ -73,12 +73,12 @@ fun main1() {
} }
fun test() { fun test() {
<!UNRESOLVED_REFERENCE!>{x : Int -> 1}()<!>; <!INAPPLICABLE_CANDIDATE!>{x : Int -> 1}()<!>;
<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!> <!INAPPLICABLE_CANDIDATE!>(fun Int.() = 1)()<!>
"sd".<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!> "sd".<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!>
val i : Int? = null val i : Int? = null
i.<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!>; i.<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!>;
<!UNRESOLVED_REFERENCE!>{}<Int>()<!> {}<Int>()
1?.<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!> 1?.<!UNRESOLVED_REFERENCE!>(fun Int.() = 1)()<!>
1.<!UNRESOLVED_REFERENCE!>{}()<!> 1.<!UNRESOLVED_REFERENCE!>{}()<!>
} }
@@ -34,7 +34,7 @@ fun foo(y: IntArray) {
@Ann1 y[0] @Ann1 y[0]
@Ann1 { x: Int -> x } @Ann1 { x: Int -> x }
@Ann1 <!UNRESOLVED_REFERENCE!>{ x: Int -> x }(1)<!> @Ann1 { x: Int -> x }(1)
@Ann1 object { fun foo() = 1 } @Ann1 object { fun foo() = 1 }
@Ann1 object { fun foo() = 1 }.foo() @Ann1 object { fun foo() = 1 }.foo()
@@ -10,7 +10,7 @@ fun test() {
val y: Unit = if (false); val y: Unit = if (false);
foo(y) foo(y)
foo(<!UNRESOLVED_REFERENCE!>{if (1==1);}()<!>) foo({if (1==1);}())
return if (true); return if (true);
} }
@@ -9,22 +9,22 @@ fun example() {
val e = if (true) {} else false val e = if (true) {} else false
val f = if (true) true else {} val f = if (true) true else {}
<!UNRESOLVED_REFERENCE!>{ {
if (true) true if (true) true
}()<!>; }();
<!UNRESOLVED_REFERENCE!>{ {
if (true) true else false if (true) true else false
}()<!>; }();
<!UNRESOLVED_REFERENCE!>{ {
if (true) {} else false if (true) {} else false
}()<!>; }();
<!UNRESOLVED_REFERENCE!>{ {
if (true) true else {} if (true) true else {}
}()<!> }()
fun t(): Boolean { fun t(): Boolean {
return if (true) true return if (true) true
@@ -10,9 +10,9 @@ fun testAnnotatedLambdaLabel() = lambda@ @Ann {}
fun testParenthesizedLambdaLabel() = lambda@ ( {} ) fun testParenthesizedLambdaLabel() = lambda@ ( {} )
fun testLabelBoundToInvokeOperatorExpression() = l@ <!UNRESOLVED_REFERENCE!>{ 42 }()<!> fun testLabelBoundToInvokeOperatorExpression() = l@ { 42 }()
fun testLabelBoundToLambda() = <!UNRESOLVED_REFERENCE!>(l@ { 42 })()<!> fun testLabelBoundToLambda() = (l@ { 42 })()
fun testWhileLoopLabel() { fun testWhileLoopLabel() {
L@ while (true) {} L@ while (true) {}
@@ -3,8 +3,8 @@ interface Your
class My { class My {
internal val x = object : Your {} internal val x = object : Your {}
internal fun foo() = <!UNRESOLVED_REFERENCE!>{ internal fun foo() = {
class Local class Local
Local() Local()
}()<!> }()
} }
@@ -5,8 +5,8 @@ class My {
private val x = object : Your {} private val x = object : Your {}
// private from local: ??? // private from local: ???
private fun foo() = <!UNRESOLVED_REFERENCE!>{ private fun foo() = {
class Local class Local
Local() Local()
}()<!> }()
} }
@@ -2,5 +2,5 @@
val la = { a -> } val la = { a -> }
val las = { a: Int -> } val las = { a: Int -> }
val larg = <!UNRESOLVED_REFERENCE!>{ a -> }(123)<!> val larg = { a -> }(123)
val twoarg = <!UNRESOLVED_REFERENCE!>{ a, b: String, c -> }(123, "asdf", 123)<!> val twoarg = { a, b: String, c -> }(123, "asdf", 123)
@@ -1,7 +1,7 @@
fun test1(i: Int) = <!UNRESOLVED_REFERENCE!>{ i -> fun test1(i: Int) = { i ->
i i
}(i)<!> }(i)
fun test2() = <!UNRESOLVED_REFERENCE!>{ i -> i }()<!> fun test2() = <!INAPPLICABLE_CANDIDATE!>{ i -> i }()<!>
fun test3() = <!UNRESOLVED_REFERENCE!>{ i -> i }(1)<!> fun test3() = { i -> i }(1)
@@ -1,3 +1,3 @@
fun foo(a: Any) { fun foo(a: Any) {
foo(<!UNRESOLVED_REFERENCE!>{ index -> } { }<!>) foo({ index -> } { })
} }
+12 -12
View File
@@ -3,49 +3,49 @@
infix fun Function1<Int, Unit>.noInlineExt(p: Int) {} infix fun Function1<Int, Unit>.noInlineExt(p: Int) {}
inline infix fun Function1<Int, Unit>.inlineExt2(p: Int) { inline infix fun Function1<Int, Unit>.inlineExt2(p: Int) {
<!UNRESOLVED_REFERENCE!>{ {
noInlineExt(11) noInlineExt(11)
this.noInlineExt(11) this.noInlineExt(11)
this noInlineExt 11 this noInlineExt 11
this this
}()<!> }()
} }
inline fun Function1<Int, Unit>.inlineExt() { inline fun Function1<Int, Unit>.inlineExt() {
<!UNRESOLVED_REFERENCE!>{ {
inlineExt2(1) inlineExt2(1)
this.inlineExt2(1) this.inlineExt2(1)
this inlineExt2 1 this inlineExt2 1
this(11) this(11)
}()<!> }()
} }
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit) { inline fun inlineFunWithInvoke(s: (p: Int) -> Unit) {
<!UNRESOLVED_REFERENCE!>{ {
s(11) s(11)
s.invoke(11) s.invoke(11)
s invoke 11 s invoke 11
}()<!> }()
} }
inline fun inlineFunWithInvokeNonInline(noinline s: (p: Int) -> Unit) { inline fun inlineFunWithInvokeNonInline(noinline s: (p: Int) -> Unit) {
<!UNRESOLVED_REFERENCE!>{ {
s(11) s(11)
s.invoke(11) s.invoke(11)
s invoke 11 s invoke 11
}()<!> }()
} }
inline fun testExtension(s: (p: Int) -> Unit) { inline fun testExtension(s: (p: Int) -> Unit) {
<!UNRESOLVED_REFERENCE!>{ {
s.inlineExt() s.inlineExt()
} ()<!> } ()
} }
inline fun inlineFunWrongExtension(s: (p: Int) -> Unit) { inline fun inlineFunWrongExtension(s: (p: Int) -> Unit) {
<!UNRESOLVED_REFERENCE!>{ {
s.noInlineExt(11) s.noInlineExt(11)
} ()<!> } ()
} }
@@ -1,13 +1,13 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE
inline fun <R> inlineFunOnlyLocal(crossinline p: () -> R) { inline fun <R> inlineFunOnlyLocal(crossinline p: () -> R) {
<!UNRESOLVED_REFERENCE!>{ {
p() p()
}()<!> }()
} }
inline fun <R> inlineFun(p: () -> R) { inline fun <R> inlineFun(p: () -> R) {
<!UNRESOLVED_REFERENCE!>{ {
p() p()
}()<!> }()
} }
@@ -17,23 +17,23 @@ inline fun inlineFunWrongUsageExt(ext: Int.(p: Int) -> Unit) {
} }
inline fun inlineFunWrongUsageInClosure(s: (p: Int) -> Unit) { inline fun inlineFunWrongUsageInClosure(s: (p: Int) -> Unit) {
<!UNRESOLVED_REFERENCE!>{ {
s s
if (true) s else 0 if (true) s else 0
s ?: s s ?: s
}()<!> }()
} }
inline fun inlineFunWrongUsageInClosureExt(ext: Int.(p: Int) -> Unit) { inline fun inlineFunWrongUsageInClosureExt(ext: Int.(p: Int) -> Unit) {
<!UNRESOLVED_REFERENCE!>{ {
ext ext
if (true) ext else 0 if (true) ext else 0
ext ?: ext ext ?: ext
}()<!> }()
} }
inline fun inlineFunNoInline(noinline s: (p: Int) -> Unit) { inline fun inlineFunNoInline(noinline s: (p: Int) -> Unit) {
@@ -1,6 +1,6 @@
// See KT-9134: smart cast is not provided inside lambda call // See KT-9134: smart cast is not provided inside lambda call
fun bar(): Int = <!UNRESOLVED_REFERENCE!>{ fun bar(): Int = {
var i: Int? var i: Int?
i = 42 i = 42
i i
}()<!> }()
@@ -4,8 +4,8 @@
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
annotation class My annotation class My
fun bar(): Int = @My <!UNRESOLVED_REFERENCE!>{ fun bar(): Int = @My {
var i: Int? var i: Int?
i = 42 i = 42
i i
}()<!> }()
@@ -48,11 +48,11 @@ import api.*
fun useAll() { fun useAll() {
@OptIn(ExperimentalAPI::class) @OptIn(ExperimentalAPI::class)
<!UNRESOLVED_REFERENCE!>{ {
function() function()
property property
val s: Typealias = "" val s: Typealias = ""
}()<!> }()
} }
@OptIn(ExperimentalAPI::class) @OptIn(ExperimentalAPI::class)