diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/instanceAccessBeforeSuperCall.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/instanceAccessBeforeSuperCall.kt index 31ffed6cc45..bd69a862cac 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/instanceAccessBeforeSuperCall.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/instanceAccessBeforeSuperCall.kt @@ -22,9 +22,9 @@ class D { fun main() { val x1: String.() -> String = if (true) { - { this } + { this } } else { - { this } + { this } } } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/instanceAccessBeforeSuperCall.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/instanceAccessBeforeSuperCall.txt index e6cb08d8e8a..5eb272b5c7f 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/instanceAccessBeforeSuperCall.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/instanceAccessBeforeSuperCall.txt @@ -47,14 +47,14 @@ FILE: instanceAccessBeforeSuperCall.kt public final fun main(): R|kotlin/Unit| { lval x1: R|kotlin/String.() -> kotlin/String| = when () { Boolean(true) -> { - fun (it: R|kotlin/String|): R|ERROR CLASS: 'this' is not defined in this context| { - ^ this# + fun R|kotlin/String|.(): R|kotlin/String| { + ^ this@R|special/anonymous| } } else -> { - fun (it: R|kotlin/String|): R|ERROR CLASS: 'this' is not defined in this context| { - ^ this# + fun R|kotlin/String|.(): R|kotlin/String| { + ^ this@R|special/anonymous| } } diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/kt41989.kt b/compiler/fir/analysis-tests/testData/resolve/inference/kt41989.kt new file mode 100644 index 00000000000..eb4b875a0cc --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/inference/kt41989.kt @@ -0,0 +1,18 @@ +// ISSUE: KT-41989 + +interface A + +interface B { + fun A.withBottomBorder(): A = this +} + +interface C : B { + val lineCellStyle: (A.() -> Unit)? + get() = if (cond()) { + { + withBottomBorder() + } + } else null +} + +fun cond(): Boolean = true diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/kt41989.txt b/compiler/fir/analysis-tests/testData/resolve/inference/kt41989.txt new file mode 100644 index 00000000000..4bf76840f42 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/inference/kt41989.txt @@ -0,0 +1,30 @@ +FILE: kt41989.kt + public abstract interface A : R|kotlin/Any| { + } + public abstract interface B : R|kotlin/Any| { + public open fun R|A|.withBottomBorder(): R|A| { + ^withBottomBorder this@R|/B.withBottomBorder| + } + + } + public abstract interface C : R|B| { + public open val lineCellStyle: R|A.() -> kotlin/Unit| + public get(): R|A.() -> kotlin/Unit| { + ^ when () { + R|/cond|() -> { + fun R|A|.(): R|kotlin/Unit| { + (this@R|/C|, this@R|special/anonymous|).R|/B.withBottomBorder|() + } + + } + else -> { + Null(null) + } + } + + } + + } + public final fun cond(): R|kotlin/Boolean| { + ^cond Boolean(true) + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 30804f87cc2..52742ffa35b 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -1739,6 +1739,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/inference/intersectionTypesInConstraints.kt"); } + @TestMetadata("kt41989.kt") + public void testKt41989() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/inference/kt41989.kt"); + } + @TestMetadata("lambdaAsReturnStatementOfLambda.kt") public void testLambdaAsReturnStatementOfLambda() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaAsReturnStatementOfLambda.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 67e609ec594..11cac10af19 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -1739,6 +1739,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/inference/intersectionTypesInConstraints.kt"); } + @TestMetadata("kt41989.kt") + public void testKt41989() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/inference/kt41989.kt"); + } + @TestMetadata("lambdaAsReturnStatementOfLambda.kt") public void testLambdaAsReturnStatementOfLambda() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaAsReturnStatementOfLambda.kt"); diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt index 50f70ccc588..fe651b30902 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt @@ -64,3 +64,6 @@ val ConeAttributes.exact: CompilerConeAttributes.Exact? by ConeAttributes.attrib val ConeAttributes.noInfer: CompilerConeAttributes.NoInfer? by ConeAttributes.attributeAccessor() val ConeAttributes.extensionFunctionType: CompilerConeAttributes.ExtensionFunctionType? by ConeAttributes.attributeAccessor() val ConeAttributes.unsafeVarianceType: CompilerConeAttributes.UnsafeVariance? by ConeAttributes.attributeAccessor() + +val ConeKotlinType.isExtensionFunctionType: Boolean + get() = attributes.extensionFunctionType != null diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt index b8db4f0e088..4de801f2c5e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt @@ -139,9 +139,7 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) { c.notFixedTypeVariables.getValue(variable.typeConstructor), TypeVariableDirectionCalculator.ResolveDirection.TO_SUPERTYPE ) as ConeKotlinType).lowerBoundIfFlexible() - val isExtensionWithoutParameters = false -// TODO -// functionalType.isExtensionFunctionType && functionalType.arguments.size == 2 && parameterTypes?.isEmpty() == true + val isExtensionWithoutParameters = functionalType.isExtensionFunctionType && functionalType.typeArguments.size == 2 && parameterTypes?.isEmpty() == true if (parameterTypes?.all { type -> type != null } == true && !isExtensionWithoutParameters) return this if (!functionalType.isSuitable()) return this require(functionalType is ConeClassLikeType) @@ -151,7 +149,8 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) { val expectedType = ConeClassLikeTypeImpl( lookupTag = functionalType.lookupTag, typeArguments = (functionalType.typeArguments.dropLast(1) + returnVariable.defaultType).toTypedArray(), - isNullable = functionalType.isNullable + isNullable = functionalType.isNullable, + attributes = functionalType.attributes ) csBuilder.addSubtypeConstraint( diff --git a/compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt b/compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt index 915a0bbbd80..853c7202589 100644 --- a/compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt +++ b/compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt @@ -1,6 +1,5 @@ // WITH_RUNTIME // KJS_WITH_FULL_RUNTIME -// IGNORE_BACKEND_FIR: JVM_IR interface Stroke interface Fill @@ -64,4 +63,4 @@ fun box(): String { test2() return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.fir.kt b/compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.fir.kt index decca17d2d2..e2d534ab09f 100644 --- a/compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.fir.kt @@ -142,8 +142,8 @@ fun main() { val x18: (C) -> Unit = select(id { it }, { it }, id<(B) -> Unit> { x -> x }) // Resolution of extension/non-extension functions combination - val x19: String.() -> Unit = select(")!>id { this }, ")!>id(fun(x: String) {})) - val x20: String.() -> Unit = select(")!>{ this }, (fun(x: String) {})) + val x19: String.() -> Unit = select(")!>id { this }, ")!>id(fun(x: String) {})) + val x20: String.() -> Unit = select(")!>{ this }, (fun(x: String) {})) val x21: String.() -> Unit = select(")!>id(fun(x: String) {}), ")!>id(fun(x: String) {})) select(id Unit>(fun(x: String) {}), ")!>id(fun(x: String) {})) select(")!>id(fun String.(x: String) {}), ")!>id(fun(x: String, y: String) {})) diff --git a/compiler/testData/diagnostics/tests/inference/extensionLambdasAndArrow.fir.kt b/compiler/testData/diagnostics/tests/inference/extensionLambdasAndArrow.fir.kt index 98da1c2d62a..1e63cd4b0d3 100644 --- a/compiler/testData/diagnostics/tests/inference/extensionLambdasAndArrow.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/extensionLambdasAndArrow.fir.kt @@ -3,14 +3,14 @@ fun select(vararg x: T) = x[0] fun main() { - val x1: String.() -> String = if (true) {{ this }} else {{ this }} - val x2: String.() -> String = if (true) {{ -> this }} else {{ -> this }} + val x1: String.() -> String = if (true) {{ this }} else {{ this }} + val x2: String.() -> String = if (true) {{ -> this }} else {{ -> this }} val x3: () -> String = if (true) {{ -> "this" }} else {{ -> "this" }} val x4: String.() -> String = if (true) {{ str: String -> "this" }} else {{ str: String -> "this" }} val x41: String.(String) -> String = if (true) {{ str: String, str2: String -> "this" }} else {{ str: String, str2: String -> "this" }} val x42: String.(String) -> String = if (true) {{ str, str2 -> "this" }} else {{ str, str2 -> "this" }} val x5: String.() -> String = if (true) {{ str -> "this" }} else {{ str -> "this" }} val x6: String.() -> String = if (true) {{ str -> "this" }} else {{ "this" }} - val x7: String.() -> String = select({ -> this }, { -> this }) - val x8: String.() -> String = select({ this }, { this }) + val x7: String.() -> String = select({ -> this }, { -> this }) + val x8: String.() -> String = select({ this }, { this }) } diff --git a/compiler/testData/diagnostics/tests/inference/kt36819.fir.kt b/compiler/testData/diagnostics/tests/inference/kt36819.fir.kt deleted file mode 100644 index 04bb45ceaa3..00000000000 --- a/compiler/testData/diagnostics/tests/inference/kt36819.fir.kt +++ /dev/null @@ -1,47 +0,0 @@ -// !LANGUAGE: +NewInference -// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_ANONYMOUS_PARAMETER -CAST_NEVER_SUCCEEDS -// ISSUE: KT-36819 - -// Case 1 - -fun select(vararg x: K) = x[0] -interface A -class B: A -class C: A -fun id1(x: T): T = x -fun id2(x: R): R = x - -class Out(x: R) - -fun main() { - val x1 = select(id1 { B() }, id2 { C() }) - val x2 = select({ B() }, { C() }) - val x3 = select(id1(Out(B())), id2(Out(C()))) -} - -// Case 2 - -fun fold(initial: R, operation: (R) -> Unit) {} - -fun foo() { - fold({ x: Int -> x }) { acc -> } -} - -// Case 3 - -class Foo - -typealias X = Foo.(Foo.() -> Unit) -> Unit - -fun bar() { - val y = when { - false -> { _ -> - Unit - } - true -> null as X - else -> { x -> - x() - Unit - } - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/kt36819.kt b/compiler/testData/diagnostics/tests/inference/kt36819.kt index 6b70c200def..982d2cb4ce1 100644 --- a/compiler/testData/diagnostics/tests/inference/kt36819.kt +++ b/compiler/testData/diagnostics/tests/inference/kt36819.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +NewInference // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_ANONYMOUS_PARAMETER -CAST_NEVER_SUCCEEDS // ISSUE: KT-36819 diff --git a/compiler/testData/diagnostics/tests/regressions/kt30245.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt30245.fir.kt index fb127e776dd..4b6806e2ab7 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt30245.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt30245.fir.kt @@ -39,8 +39,8 @@ class W4(val f: L2) { fun test1() { // to extension lambda 0 val w10 = W1 { this } // oi+ ni+ - val i10: E0 = id { this } // o1- ni+ - val j10 = id { this } // oi+ ni+ + val i10: E0 = id { this } // o1- ni+ + val j10 = id { this } // oi+ ni+ val f10 = W1(fun Int.(): Int = this) // oi+ ni+ val g10: E0 = id(fun Int.(): Int = this) // oi+ ni+ @@ -60,23 +60,23 @@ fun test1() { // to extension lambda 0 fun test2() { // to extension lambda 1 val w20 = W2 { this + it.length } // oi+ ni+ - val i20: E1 = id { this + it.length } // oi- ni+ + val i20: E1 = id { this + it.length } // oi- ni+ val w21 = W2 { this } // oi+ ni+ - val i21: E1 = id { this } // oi- ni+ + val i21: E1 = id { this } // oi- ni+ val f21 = W2(fun Int.(String): Int = this) // oi+ ni+ val g21: E1 = id(fun Int.(String): Int = this) // oi+ ni+ val w22 = W2 { s -> this + s.length } // oi+ ni+ - val i22: E1 = id { s -> this + s.length } // oi+ ni+ + val i22: E1 = id { s -> this + s.length } // oi+ ni+ val w23 = W2 { s -> s.length } // oi+ ni+ - val i23: E1 = id { s -> s.length } // oi+ ni+ + val i23: E1 = id { s -> s.length } // oi+ ni+ val w24 = W2 { s: String -> this + s.length } // oi+ ni+ - val i24: E1 = id { s: String -> this + s.length } //oi- ni+ + val i24: E1 = id { s: String -> this + s.length } //oi- ni+ val w25 = W2 { s: String -> s.length } // oi+ ni+ val i25: E1 = id { s: String -> s.length } // oi- ni+ - val w26 = W2(id { s: String -> this + s.length }) // oi- ni+ - val w26a = W2(id { s -> this + s.length }) // oi+ ni+ - val i26: E1 = id { s: String -> this + s.length } // oi- ni+ - val i26a: E1 = id { s -> this + s.length } // oi+ ni+ + val w26 = W2(id { s: String -> this + s.length }) // oi- ni+ + val w26a = W2(id { s -> this + s.length }) // oi+ ni+ + val i26: E1 = id { s: String -> this + s.length } // oi- ni+ + val i26a: E1 = id { s -> this + s.length } // oi+ ni+ val e = E.VALUE val w27 = W2(when (e) { E.VALUE -> { s: String -> this + s.length } }) // oi- ni+ val w27a = W2(when (e) { E.VALUE -> { s -> this + s.length } }) // oi+ ni+ @@ -84,7 +84,7 @@ fun test2() { // to extension lambda 1 val i27a: E1 = when (e) { E.VALUE -> { s -> this + s.length } } // oi+ ni+ val w28 = W2 { i: Int, s -> i + s.length } // oi- ni- - val i28: E1 = id { i: Int, s -> i + s.length } // oi- ni- + val i28: E1 = id { i: Int, s -> i + s.length } // oi- ni- val w29 = W2 { i: Int, s: String -> i + s.length } // oi- ni- val i29: E1 = id { i: Int, s: String -> i + s.length } // oi+ ni+