[FIR] Fix lambda resolve in independent context
This commit is contained in:
+6
-7
@@ -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!>{}()<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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);
|
||||||
}
|
}
|
||||||
+8
-8
@@ -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
|
||||||
|
|||||||
+2
-2
@@ -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)
|
||||||
+4
-4
@@ -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
@@ -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)
|
||||||
} ()<!>
|
} ()
|
||||||
}
|
}
|
||||||
+4
-4
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user