diff --git a/compiler/fir/resolve/testData/resolve/arguments/lambdaInLambda2.kt b/compiler/fir/resolve/testData/resolve/arguments/lambdaInLambda2.kt
index d4663c93e87..75db95d516d 100644
--- a/compiler/fir/resolve/testData/resolve/arguments/lambdaInLambda2.kt
+++ b/compiler/fir/resolve/testData/resolve/arguments/lambdaInLambda2.kt
@@ -1,3 +1,5 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE
+
// FILE: Function.java
public interface Function {
@@ -20,7 +22,8 @@ interface PsiMethod {
interface PsiClass
fun test() {
- val processor = AdapterProcessor(
+ // TODO: don't forget to implement preservation flexibility of java type parameters in FIR (this is the reason of error here)
+ val processor = AdapterProcessor(
Function { method: PsiMethod? -> method?.containingClass }
)
}
\ No newline at end of file
diff --git a/compiler/fir/resolve/testData/resolve/arguments/lambdaInLambda2.txt b/compiler/fir/resolve/testData/resolve/arguments/lambdaInLambda2.txt
index cdbb4211467..91f264912d5 100644
--- a/compiler/fir/resolve/testData/resolve/arguments/lambdaInLambda2.txt
+++ b/compiler/fir/resolve/testData/resolve/arguments/lambdaInLambda2.txt
@@ -7,7 +7,7 @@ FILE: main.kt
public abstract interface PsiClass : R|kotlin/Any| {
}
public final fun test(): R|kotlin/Unit| {
- lval processor: R|AdapterProcessor| = R|/AdapterProcessor.AdapterProcessor|(R|/Function|!|>( = Function@fun (method: R|PsiMethod?|): R|PsiClass?| {
+ lval processor: = #(R|/Function|( = Function@fun (method: R|PsiMethod?|): R|PsiClass?| {
R|/method|?.R|/PsiMethod.containingClass|
}
))
diff --git a/compiler/fir/resolve/testData/resolve/samConstructors/genericSam.txt b/compiler/fir/resolve/testData/resolve/samConstructors/genericSam.txt
index bf582bc78d8..cc75257ed31 100644
--- a/compiler/fir/resolve/testData/resolve/samConstructors/genericSam.txt
+++ b/compiler/fir/resolve/testData/resolve/samConstructors/genericSam.txt
@@ -4,11 +4,11 @@ FILE: main.kt
R|/x|.R|kotlin/Int.toInt|().R|kotlin/Any.toString|()
}
)
- R|/MyFunction|( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| {
+ R|/MyFunction|!|, R|ft!|>( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| {
R|/x|.R|kotlin/Any.toString|()
}
)
- R|/MyFunction|( = MyFunction@fun (x: R|kotlin/Any?|): R|kotlin/String| {
+ R|/MyFunction|!|>( = MyFunction@fun (x: R|kotlin/Any?|): R|kotlin/String| {
String()
}
)
diff --git a/compiler/fir/resolve/testData/resolve/samConstructors/genericSamInferenceFromExpectType.txt b/compiler/fir/resolve/testData/resolve/samConstructors/genericSamInferenceFromExpectType.txt
index fa3a3eb10fa..4db6916c001 100644
--- a/compiler/fir/resolve/testData/resolve/samConstructors/genericSamInferenceFromExpectType.txt
+++ b/compiler/fir/resolve/testData/resolve/samConstructors/genericSamInferenceFromExpectType.txt
@@ -10,19 +10,19 @@ FILE: main.kt
R|/x|.R|kotlin/Int.toInt|().R|kotlin/Any.toString|()
}
))
- R|/foo2|(R|/MyFunction|( = MyFunction@fun (x: R|kotlin/Number|): R|kotlin/String| {
+ R|/foo2|(R|/MyFunction|!|>( = MyFunction@fun (x: R|kotlin/Number|): R|kotlin/String| {
R|/x|.R|kotlin/Number.toInt|().R|kotlin/Any.toString|()
}
))
- #(R|/MyFunction|( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| {
+ #(R|/MyFunction|!|, R|ft!|>( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| {
R|/x|.R|kotlin/Any.toString|()
}
))
- R|/foo3|(R|/MyFunction|( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| {
+ R|/foo3|!|>(R|/MyFunction|!|>( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| {
R|/x|.R|kotlin/Int.plus|(Int(1)).R|kotlin/Any.toString|()
}
), Int(1))
- R|/foo3|(R|/MyFunction|( = MyFunction@fun (x: R|kotlin/Number|): R|kotlin/String| {
+ R|/foo3|!|>(R|/MyFunction|!|>( = MyFunction@fun (x: R|kotlin/Number|): R|kotlin/String| {
R|/x|.R|kotlin/Number.toInt|().R|kotlin/Any.toString|()
}
), Int(2))
diff --git a/compiler/fir/resolve/testData/resolve/samConversions/genericSam.txt b/compiler/fir/resolve/testData/resolve/samConversions/genericSam.txt
index 9b24f2f4e77..3d5f0ed8e3e 100644
--- a/compiler/fir/resolve/testData/resolve/samConversions/genericSam.txt
+++ b/compiler/fir/resolve/testData/resolve/samConversions/genericSam.txt
@@ -12,11 +12,11 @@ FILE: main.kt
R|/x|.R|kotlin/Any.toString|()
}
)
- Q|JavaUsage|.R|/JavaUsage.foo3|(foo3@fun (x: R|kotlin/Int|): R|kotlin/Unit| {
+ Q|JavaUsage|.R|/JavaUsage.foo3|!|>(foo3@fun (x: R|kotlin/Int|): R|kotlin/String| {
R|/x|.R|kotlin/Int.plus|(Int(1)).R|kotlin/Any.toString|()
}
, Int(1))
- Q|JavaUsage|.R|/JavaUsage.foo3|(foo3@fun (x: R|kotlin/Number|): R|kotlin/Unit| {
+ Q|JavaUsage|.R|/JavaUsage.foo3|!|>(foo3@fun (x: R|kotlin/Number|): R|kotlin/String| {
R|/x|.R|kotlin/Number.toInt|().R|kotlin/Any.toString|()
}
, Int(2))
diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/StaticGenericMethod.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/StaticGenericMethod.txt
index d2614e93033..c0fb95bdb4a 100644
--- a/compiler/fir/resolve/testData/resolve/stdlib/j+k/StaticGenericMethod.txt
+++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/StaticGenericMethod.txt
@@ -13,7 +13,7 @@ FILE: User.kt
protected abstract fun createSettings(): R|T|
public final fun foo(): R|kotlin/Unit| {
- this@R|/User|.R|FakeOverride| = Q|StaticOwner|.R|/StaticOwner.newInstance|(this@R|/User|.R|FakeOverride|.R|kotlin/jvm/javaClass|)
+ this@R|/User|.R|FakeOverride| = Q|StaticOwner|.R|/StaticOwner.newInstance|!|>(this@R|/User|.R|FakeOverride|.R|kotlin/jvm/javaClass|)
}
}
diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java
index 404218fba77..2c46558a08b 100644
--- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java
+++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java
@@ -8092,6 +8092,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/functionLiterals/LabeledFunctionLiterals.kt");
}
+ @TestMetadata("lambdaInLambda2.kt")
+ public void testLambdaInLambda2() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.kt");
+ }
+
@TestMetadata("prematurelyAnalyzingLambdaWhileFixingTypeVariableForAnotherArgument.kt")
public void testPrematurelyAnalyzingLambdaWhileFixingTypeVariableForAnotherArgument() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/prematurelyAnalyzingLambdaWhileFixingTypeVariableForAnotherArgument.kt");
@@ -14893,6 +14898,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/nullableTypes/elvisOnUnit.kt");
}
+ @TestMetadata("inferenceFlexibleTToNullable.kt")
+ public void testInferenceFlexibleTToNullable() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.kt");
+ }
+
@TestMetadata("nullAssertOnTypeWithNullableUpperBound.kt")
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/nullAssertOnTypeWithNullableUpperBound.kt");
@@ -14938,6 +14948,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/nullableTypes/safeCallWithInvoke.kt");
}
+ @TestMetadata("takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt")
+ public void testTakingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt");
+ }
+
@TestMetadata("uselessElvis.kt")
public void testUselessElvis() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/uselessElvis.kt");
@@ -18918,6 +18933,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitutionKT.kt");
}
+ @TestMetadata("samConversionToGeneric.kt")
+ public void testSamConversionToGeneric() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.kt");
+ }
+
+ @TestMetadata("samConversionsWithSmartCasts.kt")
+ public void testSamConversionsWithSmartCasts() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.kt");
+ }
+
@TestMetadata("sameCandidatesFromKotlinAndJavaInOneScope.kt")
public void testSameCandidatesFromKotlinAndJavaInOneScope() throws Exception {
runTest("compiler/testData/diagnostics/tests/samConversions/sameCandidatesFromKotlinAndJavaInOneScope.kt");
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt
index afe704aecd1..456af5d9209 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
+import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.*
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.context.CallPosition
import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
+import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.inference.components.composeWith
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.inference.substitute
@@ -53,6 +55,8 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate
import org.jetbrains.kotlin.types.typeUtil.contains
+import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
+import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.*
@@ -711,8 +715,39 @@ class NewResolvedCallImpl(
calculateExpectedTypeForSamConvertedArgumentMap(substitutor)
}
+ private fun KotlinType.withNullabilityFromExplicitTypeArgument(typeArgument: SimpleTypeArgument) =
+ (if (typeArgument.type.isMarkedNullable) makeNullable() else makeNotNullable()).unwrap()
+
+ private fun getSubstitutorWithoutFlexibleTypes(
+ currentSubstitutor: NewTypeSubstitutor?,
+ explicitTypeArguments: List
+ ): NewTypeSubstitutor? {
+ if (currentSubstitutor !is NewTypeSubstitutorByConstructorMap || explicitTypeArguments.isEmpty()) return currentSubstitutor
+ if (!currentSubstitutor.map.any { (_, value) -> value.isFlexible() }) return currentSubstitutor
+
+ val typeVariables = resolvedCallAtom.freshVariablesSubstitutor.freshVariables
+ val newSubstitutorMap = currentSubstitutor.map.toMutableMap()
+
+ explicitTypeArguments.forEachIndexed { index, typeArgument ->
+ val typeVariableConstructor = typeVariables.getOrNull(index)?.freshTypeConstructor ?: return@forEachIndexed
+
+ newSubstitutorMap[typeVariableConstructor] =
+ newSubstitutorMap[typeVariableConstructor]?.withNullabilityFromExplicitTypeArgument(typeArgument)
+ ?: return@forEachIndexed
+ }
+
+ return NewTypeSubstitutorByConstructorMap(newSubstitutorMap)
+ }
+
private fun substitutedResultingDescriptor(substitutor: NewTypeSubstitutor?) =
when (val candidateDescriptor = resolvedCallAtom.candidateDescriptor) {
+ is ClassConstructorDescriptor, is SyntheticMemberDescriptor<*> -> {
+ val explicitTypeArguments = resolvedCallAtom.atom.typeArguments.filterIsInstance()
+
+ candidateDescriptor.substituteInferredVariablesAndApproximate(
+ getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments)
+ )
+ }
is FunctionDescriptor -> candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
is PropertyDescriptor -> {
val shouldRunApproximation = candidateDescriptor.returnType?.let { type ->
diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt
index af6e013d21b..7baf5922a1f 100644
--- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt
+++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt
@@ -21,11 +21,10 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
import org.jetbrains.kotlin.resolve.calls.tower.InfixCallNoInfixModifier
import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorModifier
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
-import org.jetbrains.kotlin.types.ErrorUtils
-import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlin.types.TypeSubstitutor
-import org.jetbrains.kotlin.types.UnwrappedType
+import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.contains
+import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
+import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal object CheckInstantiationOfAbstractClass : ResolutionPart() {
@@ -151,7 +150,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
if (knownTypeArgument != null) {
csBuilder.addEqualityConstraint(
freshVariable.defaultType,
- knownTypeArgument.unwrap(),
+ getTypePreservingFlexibilityWrtTypeVariable(knownTypeArgument.unwrap(), freshVariable),
KnownTypeParameterConstraintPosition(knownTypeArgument)
)
continue
@@ -162,7 +161,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
if (typeArgument is SimpleTypeArgument) {
csBuilder.addEqualityConstraint(
freshVariable.defaultType,
- typeArgument.type,
+ getTypePreservingFlexibilityWrtTypeVariable(typeArgument.type, freshVariable),
ExplicitTypeParameterConstraintPosition(typeArgument)
)
} else {
@@ -173,6 +172,19 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
}
}
+ private fun TypeParameterDescriptor.shouldBeFlexible(): Boolean {
+ return upperBounds.any {
+ it.isFlexible() || ((it.constructor.declarationDescriptor as? TypeParameterDescriptor)?.run { shouldBeFlexible() } ?: false)
+ }
+ }
+
+ private fun getTypePreservingFlexibilityWrtTypeVariable(
+ type: KotlinType,
+ typeVariable: TypeVariableFromCallableDescriptor
+ ) = if (typeVariable.originalTypeParameter.shouldBeFlexible()) {
+ KotlinTypeFactory.flexibleType(type.makeNotNullable().lowerIfFlexible(), type.makeNullable().upperIfFlexible())
+ } else type
+
fun createToFreshVariableSubstitutorAndAddInitialConstraints(
candidateDescriptor: CallableDescriptor,
csBuilder: ConstraintSystemOperation
diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt
index 0b7894c0b6a..c571b921e79 100644
--- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt
+++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt
@@ -146,7 +146,7 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
*
* => Foo <: T! -- (Foo!! .. Foo) <: T
*
- * Foo? <: T! -- (Foo!! .. Foo?) <: T
+ * Foo? <: T! -- Foo? <: T
*
*
* (Foo..Bar) <: T! --
@@ -173,7 +173,11 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
when (subType) {
is SimpleTypeMarker ->
// Foo <: T! -- (Foo!! .. Foo) <: T
- createFlexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType)
+ if (subType.isMarkedNullable()) {
+ subType // prefer nullable type to flexible one: `Foo? <: (T..T?)` => lowerConstraint = `Foo?`
+ } else {
+ createFlexibleType(subType, subType.withNullability(true))
+ }
is FlexibleTypeMarker ->
// (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
@@ -197,23 +201,24 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
}
/**
- * T! <: Foo <=> T <: Foo
+ * T! <: Foo <=> T <: Foo..Foo?
* T? <: Foo <=> T <: Foo && Nothing? <: Foo
* T <: Foo -- leave as is
*/
private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
- @Suppress("NAME_SHADOWING")
- val typeVariable = typeVariable.lowerBoundIfFlexible()
+ val typeVariableLowerBound = typeVariable.lowerBoundIfFlexible()
+ val simplifiedSuperType = if (typeVariableLowerBound.isDefinitelyNotNullType()) {
+ superType.withNullability(true)
+ } else if (typeVariable.isFlexible() && superType is SimpleTypeMarker) {
+ createFlexibleType(superType, superType.withNullability(true))
+ } else superType
- @Suppress("NAME_SHADOWING")
- val superType = if (typeVariable.isDefinitelyNotNullType()) superType.withNullability(true) else superType
+ addUpperConstraint(typeVariableLowerBound.typeConstructor(), simplifiedSuperType)
- addUpperConstraint(typeVariable.typeConstructor(), superType)
-
- if (typeVariable.isMarkedNullable()) {
+ if (typeVariableLowerBound.isMarkedNullable()) {
// here is important that superType is singleClassifierType
- return superType.anyBound(this::isMyTypeVariable) ||
- isSubtypeOfByTypeChecker(nullableNothingType(), superType)
+ return simplifiedSuperType.anyBound(this::isMyTypeVariable) ||
+ isSubtypeOfByTypeChecker(nullableNothingType(), simplifiedSuperType)
}
return true
diff --git a/compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt b/compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt
new file mode 100644
index 00000000000..59a6d62dead
--- /dev/null
+++ b/compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt
@@ -0,0 +1,73 @@
+// IGNORE_BACKEND_FIR: JVM_IR
+// IGNORE_BACKEND: JS, JS_IR
+// !LANGUAGE: +NewInference
+
+// FILE: Foo.java
+import org.jetbrains.annotations.NotNull;
+
+public class Foo {
+ T x;
+
+ public Foo(T x) {
+ this.x = x;
+ }
+
+ public static Number bar() { return null; }
+
+ public static K simpleId(K k) {
+ return k;
+ }
+
+ public T produceT() {
+ return x;
+ }
+
+ @NotNull
+ public T produceNotNullT() {
+ return x;
+ }
+
+ public void consumeT(T x) {}
+}
+
+// FILE: main.kt
+fun bar(n: Number?, d: T, e: T) {
+ val b: Number? = Foo.simpleId(n)
+ b?.toInt()
+ val c = Foo.simpleId(n)
+ c?.toInt()
+
+ val x4 = Foo(if (true) 10 else null)
+ val x6: Number? = x4.produceT()
+ x6?.toInt()
+ val x7 = x4.produceT()
+ x7?.toInt()
+ val x8 = x4.produceNotNullT()
+ x8.toInt()
+
+ x4.consumeT(x7)
+
+ val x9: T = Foo.simpleId(d)
+ val x10: T? = Foo.simpleId(d)
+
+ if (e != null) {
+ var x11 = e
+ x11 = Foo.simpleId(d) // assign to definitely not-null T, the lack an error is consistent with old inference
+ }
+
+ var x11 = Foo(e).x
+ x11 = Foo.simpleId(d) // assign to flexible T
+
+ var x12 = Foo.bar()
+ x12 = Foo.simpleId(n) // assign to flexible Number
+ x12.toInt()
+
+ var x13 = e
+ x13 = Foo.simpleId(d)
+}
+
+fun box(): String {
+ bar(10, "", "")
+
+ return "OK"
+}
diff --git a/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.fir.kt b/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.fir.kt
new file mode 100644
index 00000000000..b8c30aeac8a
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.fir.kt
@@ -0,0 +1,29 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE
+
+// FILE: Function.java
+
+public interface Function {
+ Result fun(Param param);
+}
+
+// FILE: AdapterProcessor.java
+
+public class AdapterProcessor {
+ public AdapterProcessor(Function super T, ? extends S> conversion) {}
+}
+
+
+// FILE: main.kt
+
+interface PsiMethod {
+ val containingClass: PsiClass?
+}
+
+interface PsiClass
+
+fun test() {
+ // TODO: don't forget to implement preservation flexibility of java type parameters in FIR (this is the reason of error here)
+ val processor = AdapterProcessor(
+ Function { method: PsiMethod? -> method?.containingClass }
+ )
+}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.kt b/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.kt
new file mode 100644
index 00000000000..03278a8314d
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.kt
@@ -0,0 +1,29 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE
+
+// FILE: Function.java
+
+public interface Function {
+ Result fun(Param param);
+}
+
+// FILE: AdapterProcessor.java
+
+public class AdapterProcessor {
+ public AdapterProcessor(Function super T, ? extends S> conversion) {}
+}
+
+
+// FILE: main.kt
+
+interface PsiMethod {
+ val containingClass: PsiClass?
+}
+
+interface PsiClass
+
+fun test() {
+ // TODO: don't forget to implement preservation flexibility of java type parameters in FIR (this is the reason of error here)
+ val processor = AdapterProcessor(
+ Function { method: PsiMethod? -> method?.containingClass }
+ )
+}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.txt b/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.txt
new file mode 100644
index 00000000000..9d0266fc1de
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/functionLiterals/lambdaInLambda2.txt
@@ -0,0 +1,30 @@
+package
+
+public fun test(): kotlin.Unit
+
+public open class AdapterProcessor*0*/ T : kotlin.Any!, /*1*/ S : kotlin.Any!> {
+ public constructor AdapterProcessor*0*/ T : kotlin.Any!, /*1*/ S : kotlin.Any!>(/*0*/ conversion: Function!)
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface Function*0*/ Param : kotlin.Any!, /*1*/ Result : kotlin.Any!> {
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public abstract fun `fun`(/*0*/ param: Param!): Result!
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface PsiClass {
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface PsiMethod {
+ public abstract val containingClass: PsiClass?
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/diagnostics/tests/j+k/matchers.fir.kt b/compiler/testData/diagnostics/tests/j+k/matchers.fir.kt
index 6d65c7863e9..4c2bcb72eef 100644
--- a/compiler/testData/diagnostics/tests/j+k/matchers.fir.kt
+++ b/compiler/testData/diagnostics/tests/j+k/matchers.fir.kt
@@ -14,5 +14,5 @@ public class Matcher {
// FILE: main.kt
fun test(x: List) {
- Assert.assertThat(x, Matcher.hasItem("abc"))
+ Assert.assertThat(x, Matcher.hasItem("abc"))
}
diff --git a/compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.fir.kt b/compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.fir.kt
new file mode 100644
index 00000000000..5bd103abf79
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.fir.kt
@@ -0,0 +1,63 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNCHECKED_CAST -UNUSED_VALUE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
+// !LANGUAGE: +NewInference
+// SKIP_TXT
+
+// FILE: Foo.java
+import org.jetbrains.annotations.NotNull;
+
+public class Foo {
+ T x;
+
+ public Foo(T x) {
+ this.x = x;
+ }
+
+ public static Number bar() { return null; }
+
+ public static K simpleId(K k) {
+ return k;
+ }
+
+ public T produceT() {
+ return x;
+ }
+
+ @NotNull
+ public T produceNotNullT() {
+ return x;
+ }
+
+ public void consumeT(T x) {}
+}
+
+// FILE: main.kt
+fun bar(n: Number?, d: T, e: T) {
+ val a: Number = Foo.simpleId(n)
+ val b: Number? = Foo.simpleId(n)
+ val c = Foo.simpleId(n)
+
+ val x4 = Foo(if (true) 10 else null)
+ val x5: Number = x4.produceT()
+ val x6: Number? = x4.produceT()
+ val x7 = x4.produceT()
+ val x8 = x4.produceNotNullT()
+
+ x4.consumeT(x7)
+
+ val x9: T = Foo.simpleId(d)
+ val x10: T? = Foo.simpleId(d)
+
+ if (e != null) {
+ var x11 = e
+ x11 = Foo.simpleId(d) // assign to definitely not-null T, the lack an error is consistent with old inference
+ }
+
+ var x11 = Foo(null as T).x
+ x11 = Foo.simpleId(d) // assign to flexible T
+
+ var x12 = Foo.bar()
+ x12 = Foo.simpleId(n) // assign to flexible Number
+
+ var x13 = e
+ x13 = Foo.simpleId(d)
+}
diff --git a/compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.kt b/compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.kt
new file mode 100644
index 00000000000..8bda3e5676a
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.kt
@@ -0,0 +1,63 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNCHECKED_CAST -UNUSED_VALUE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
+// !LANGUAGE: +NewInference
+// SKIP_TXT
+
+// FILE: Foo.java
+import org.jetbrains.annotations.NotNull;
+
+public class Foo {
+ T x;
+
+ public Foo(T x) {
+ this.x = x;
+ }
+
+ public static Number bar() { return null; }
+
+ public static K simpleId(K k) {
+ return k;
+ }
+
+ public T produceT() {
+ return x;
+ }
+
+ @NotNull
+ public T produceNotNullT() {
+ return x;
+ }
+
+ public void consumeT(T x) {}
+}
+
+// FILE: main.kt
+fun bar(n: Number?, d: T, e: T) {
+ val a: Number = Foo.simpleId(n)
+ val b: Number? = Foo.simpleId(n)
+ val c = Foo.simpleId(n)
+
+ val x4 = Foo(if (true) 10 else null)
+ val x5: Number = x4.produceT()
+ val x6: Number? = x4.produceT()
+ val x7 = x4.produceT()
+ val x8 = x4.produceNotNullT()
+
+ x4.consumeT(x7)
+
+ val x9: T = Foo.simpleId(d)
+ val x10: T? = Foo.simpleId(d)
+
+ if (e != null) {
+ var x11 = e
+ x11 = Foo.simpleId(d) // assign to definitely not-null T, the lack an error is consistent with old inference
+ }
+
+ var x11 = Foo(null as T).x
+ x11 = Foo.simpleId(d) // assign to flexible T
+
+ var x12 = Foo.bar()
+ x12 = Foo.simpleId(n) // assign to flexible Number
+
+ var x13 = e
+ x13 = Foo.simpleId(d)
+}
diff --git a/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.fir.kt b/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.fir.kt
new file mode 100644
index 00000000000..2be852d310e
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.fir.kt
@@ -0,0 +1,38 @@
+// !LANGUAGE: +NewInference
+
+// It's relevant only for Java constructor calls
+
+// FILE: J.java
+
+public class J {}
+
+// FILE: main.kt
+
+import java.util.ArrayList
+
+class Foo(val attributes: Map)
+
+class A
+
+class Bar {
+ val foos1 = ArrayList()
+ val foos2 = ArrayList()
+ val foos3 = ArrayList>()
+ val foos4 = ArrayList?>()
+ val foos5 = ArrayList?>()
+ val foos6 = ArrayList>()
+ val foos7 = ArrayList()
+ val foos8 = ArrayList()
+ val foos9 = ArrayList()
+ val foos10 = ArrayList()
+ val foos11 = ArrayList>()
+ val foos12 = ArrayList>()
+ val foos13 = ArrayList>()
+ val foos14 = ArrayList?>()
+ val foos15 = ArrayList>()
+
+ val foos16 = J()
+ val foos17 = J()
+ val foos18 = J()
+ val foos19 = J()
+}
diff --git a/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt b/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt
new file mode 100644
index 00000000000..381be01fd41
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.kt
@@ -0,0 +1,38 @@
+// !LANGUAGE: +NewInference
+
+// It's relevant only for Java constructor calls
+
+// FILE: J.java
+
+public class J {}
+
+// FILE: main.kt
+
+import java.util.ArrayList
+
+class Foo(val attributes: Map)
+
+class A
+
+class Bar {
+ val foos1 = ")!>ArrayList()
+ val foos2 = ")!>ArrayList()
+ val foos3 = >")!>ArrayList>()
+ val foos4 = ?>")!>ArrayList?>()
+ val foos5 = ?>")!>ArrayList?>()
+ val foos6 = >")!>ArrayList>()
+ val foos7 = ")!>ArrayList()
+ val foos8 = ")!>ArrayList()
+ val foos9 = ")!>ArrayList()
+ val foos10 = ")!>ArrayList()
+ val foos11 = >")!>ArrayList>()
+ val foos12 = >")!>ArrayList>()
+ val foos13 = >")!>ArrayList>()
+ val foos14 = ?>")!>ArrayList?>()
+ val foos15 = >")!>ArrayList>()
+
+ val foos16 = ")!>J<Foo>()
+ val foos17 = ")!>J<Foo?>()
+ val foos18 = ")!>J<T>()
+ val foos19 = ")!>J<T?>()
+}
diff --git a/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.txt b/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.txt
new file mode 100644
index 00000000000..66f3922d85a
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/nullableTypes/takingNullabilityFromExplicitTypeArgmentsInsteadOfUsingFlexibleTypes.txt
@@ -0,0 +1,49 @@
+package
+
+public final class A*0*/ R> {
+ public constructor A*0*/ R>()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public final class Bar*0*/ T, /*1*/ K : kotlin.Any> {
+ public constructor Bar*0*/ T, /*1*/ K : kotlin.Any>()
+ public final val foos1: java.util.ArrayList
+ public final val foos10: java.util.ArrayList
+ public final val foos11: java.util.ArrayList>
+ public final val foos12: java.util.ArrayList>
+ public final val foos13: java.util.ArrayList>
+ public final val foos14: java.util.ArrayList?>
+ public final val foos15: java.util.ArrayList>
+ public final val foos16: J
+ public final val foos17: J
+ public final val foos18: J
+ public final val foos19: J
+ public final val foos2: java.util.ArrayList
+ public final val foos3: java.util.ArrayList>
+ public final val foos4: java.util.ArrayList?>
+ public final val foos5: java.util.ArrayList?>
+ public final val foos6: java.util.ArrayList>
+ public final val foos7: java.util.ArrayList
+ public final val foos8: java.util.ArrayList
+ public final val foos9: java.util.ArrayList
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public final class Foo {
+ public constructor Foo(/*0*/ attributes: kotlin.collections.Map)
+ public final val attributes: kotlin.collections.Map
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public open class J*0*/ T : kotlin.Int!> {
+ public constructor J*0*/ T : kotlin.Int!>()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/diagnostics/tests/platformTypes/methodCall/singleton.kt b/compiler/testData/diagnostics/tests/platformTypes/methodCall/singleton.kt
index 0b3a5adc06d..8a6b6df8bcb 100644
--- a/compiler/testData/diagnostics/tests/platformTypes/methodCall/singleton.kt
+++ b/compiler/testData/diagnostics/tests/platformTypes/methodCall/singleton.kt
@@ -5,6 +5,6 @@ interface Foo
fun test() {
var nullable: Foo? = null
- val foo: Collection = java.util.Collections.singleton(nullable)
+ val foo: Collection = java.util.Collections.singleton(nullable)
val foo1: Collection = java.util.Collections.singleton(nullable!!)
}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.fir.kt b/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.fir.kt
new file mode 100644
index 00000000000..54f85636763
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.fir.kt
@@ -0,0 +1,58 @@
+// !LANGUAGE: +NewInference
+
+// FILE: samConversionToGeneric.kt
+
+fun test1() = J { x -> x }
+
+fun test2() = J { x: String -> x }
+
+fun test3() = H.bar { x: String -> x }
+
+fun test4(a: Any) {
+ a as J
+ H.bar(a)
+}
+
+fun test5(a: Any) {
+ a as (String) -> String
+ H.bar(a)
+}
+
+fun test6(a: (T) -> T) {
+ H.bar(a)
+}
+
+fun test7(a: Any) {
+ a as (T) -> T
+ H.bar(a)
+}
+
+fun test8(efn: String.() -> String) = J(efn)
+
+fun test9(efn: String.() -> String) {
+ H.bar(efn)
+}
+
+fun test10(fn: (Int) -> String) {
+ H.bar2x(fn)
+}
+
+// FILE: J.java
+public interface J {
+ T foo(T x);
+}
+
+// FILE: J2.java
+public interface J2 {
+ T1 foo(T2 x);
+}
+
+// FILE: J2X.java
+public interface J2X extends J2 {
+}
+
+// FILE: H.java
+public class H {
+ public static void bar(J j) {}
+ public static void bar2x(J2X j2x) {}
+}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.kt b/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.kt
new file mode 100644
index 00000000000..b85a40a361d
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.kt
@@ -0,0 +1,58 @@
+// !LANGUAGE: +NewInference
+
+// FILE: samConversionToGeneric.kt
+
+fun test1() = J { x -> x }
+
+fun test2() = J { x: String -> x }
+
+fun test3() = H.bar { x: String -> x }
+
+fun test4(a: Any) {
+ a as J
+ H.bar(a)
+}
+
+fun test5(a: Any) {
+ a as (String) -> String
+ H.bar(a)
+}
+
+fun test6(a: (T) -> T) {
+ H.bar(a)
+}
+
+fun test7(a: Any) {
+ a as (T) -> T
+ H.bar(a)
+}
+
+fun test8(efn: String.() -> String) = J(efn)
+
+fun test9(efn: String.() -> String) {
+ H.bar(efn)
+}
+
+fun test10(fn: (Int) -> String) {
+ H.bar2x(fn)
+}
+
+// FILE: J.java
+public interface J {
+ T foo(T x);
+}
+
+// FILE: J2.java
+public interface J2 {
+ T1 foo(T2 x);
+}
+
+// FILE: J2X.java
+public interface J2X extends J2 {
+}
+
+// FILE: H.java
+public class H {
+ public static void bar(J j) {}
+ public static void bar2x(J2X j2x) {}
+}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.txt b/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.txt
new file mode 100644
index 00000000000..fe5a34fe46b
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/samConversions/samConversionToGeneric.txt
@@ -0,0 +1,44 @@
+package
+
+public fun test1(): J
+public fun test10(/*0*/ fn: (kotlin.Int) -> kotlin.String): kotlin.Unit
+public fun test2(): J
+public fun test3(): kotlin.Unit
+public fun test4(/*0*/ a: kotlin.Any): kotlin.Unit
+public fun test5(/*0*/ a: kotlin.Any): kotlin.Unit
+public fun *0*/ T> test6(/*0*/ a: (T) -> T): kotlin.Unit
+public fun *0*/ T> test7(/*0*/ a: kotlin.Any): kotlin.Unit
+public fun test8(/*0*/ efn: kotlin.String.() -> kotlin.String): J
+public fun test9(/*0*/ efn: kotlin.String.() -> kotlin.String): kotlin.Unit
+
+public open class H {
+ public constructor H()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+
+ // Static members
+ public open fun *0*/ X : kotlin.Any!> bar(/*0*/ j: J!): kotlin.Unit
+ public open fun *0*/ Y : kotlin.Any!> bar2x(/*0*/ j2x: J2X!): kotlin.Unit
+}
+
+public interface J*0*/ T : kotlin.Any!> {
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public abstract fun foo(/*0*/ x: T!): T!
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface J2*0*/ T1 : kotlin.Any!, /*1*/ T2 : kotlin.Any!> {
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public abstract fun foo(/*0*/ x: T2!): T1!
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface J2X*0*/ T3 : kotlin.Any!> : J2 {
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ x: T3!): kotlin.String!
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.fir.kt b/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.fir.kt
new file mode 100644
index 00000000000..a95ff868f00
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.fir.kt
@@ -0,0 +1,72 @@
+// !LANGUAGE: +NewInference
+
+// NB new inference doesn't really work with old JVM back-end.
+
+// WITH_JDK
+// FILE: samConversionsWithSmartCasts.kt
+
+fun test1(a: () -> Unit) {
+ if (a is Runnable) {
+ J.runStatic(a)
+ }
+}
+
+fun test2(a: () -> Unit) {
+ if (a is Runnable) {
+ J().run1(a)
+ }
+}
+
+fun test3(a: () -> Unit) {
+ if (a is Runnable) {
+ J().run2(a, a)
+ }
+}
+
+fun test4(a: () -> Unit, b: () -> Unit) {
+ if (a is Runnable) {
+ J().run2(a, b)
+ }
+}
+
+fun test5(a: Any) {
+ if (a is Runnable) {
+ J().run1(a)
+ }
+}
+
+fun test5x(a: Any) {
+ if (a is Runnable) {
+ a as () -> Unit
+ J().run1(a)
+ }
+}
+
+fun test6(a: Any) {
+ a as () -> Unit
+ J().run1(a)
+}
+
+fun test7(a: (Int) -> Int) {
+ a as () -> Unit
+ J().run1(a)
+}
+
+fun test8(a: () -> Unit) {
+ J().run1(J.id(a))
+}
+
+fun test9() {
+ J().run1(::test9)
+}
+
+// FILE: J.java
+public class J {
+ public static void runStatic(Runnable r) {}
+
+ public void run1(Runnable r) {}
+
+ public void run2(Runnable r1, Runnable r2) {}
+
+ public static T id(T x) { return x; }
+}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.kt b/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.kt
new file mode 100644
index 00000000000..09931b03bd7
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.kt
@@ -0,0 +1,72 @@
+// !LANGUAGE: +NewInference
+
+// NB new inference doesn't really work with old JVM back-end.
+
+// WITH_JDK
+// FILE: samConversionsWithSmartCasts.kt
+
+fun test1(a: () -> Unit) {
+ if (a is Runnable) {
+ J.runStatic(a)
+ }
+}
+
+fun test2(a: () -> Unit) {
+ if (a is Runnable) {
+ J().run1(a)
+ }
+}
+
+fun test3(a: () -> Unit) {
+ if (a is Runnable) {
+ J().run2(a, a)
+ }
+}
+
+fun test4(a: () -> Unit, b: () -> Unit) {
+ if (a is Runnable) {
+ J().run2(a, b)
+ }
+}
+
+fun test5(a: Any) {
+ if (a is Runnable) {
+ J().run1(a)
+ }
+}
+
+fun test5x(a: Any) {
+ if (a is Runnable) {
+ a as () -> Unit
+ J().run1(a)
+ }
+}
+
+fun test6(a: Any) {
+ a as () -> Unit
+ J().run1(a)
+}
+
+fun test7(a: (Int) -> Int) {
+ a as () -> Unit
+ J().run1(a)
+}
+
+fun test8(a: () -> Unit) {
+ J().run1(J.id(a))
+}
+
+fun test9() {
+ J().run1(::test9)
+}
+
+// FILE: J.java
+public class J {
+ public static void runStatic(Runnable r) {}
+
+ public void run1(Runnable r) {}
+
+ public void run2(Runnable r1, Runnable r2) {}
+
+ public static T id(T x) { return x; }
+}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.txt b/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.txt
new file mode 100644
index 00000000000..e9e53ef5d60
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.txt
@@ -0,0 +1,25 @@
+package
+
+public fun test1(/*0*/ a: () -> kotlin.Unit): kotlin.Unit
+public fun test2(/*0*/ a: () -> kotlin.Unit): kotlin.Unit
+public fun test3(/*0*/ a: () -> kotlin.Unit): kotlin.Unit
+public fun test4(/*0*/ a: () -> kotlin.Unit, /*1*/ b: () -> kotlin.Unit): kotlin.Unit
+public fun test5(/*0*/ a: kotlin.Any): kotlin.Unit
+public fun test5x(/*0*/ a: kotlin.Any): kotlin.Unit
+public fun test6(/*0*/ a: kotlin.Any): kotlin.Unit
+public fun test7(/*0*/ a: (kotlin.Int) -> kotlin.Int): kotlin.Unit
+public fun test8(/*0*/ a: () -> kotlin.Unit): kotlin.Unit
+public fun test9(): kotlin.Unit
+
+public open class J {
+ public constructor J()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open fun run1(/*0*/ r: java.lang.Runnable!): kotlin.Unit
+ public open fun run2(/*0*/ r1: java.lang.Runnable!, /*1*/ r2: java.lang.Runnable!): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+
+ // Static members
+ public open fun *0*/ T : kotlin.Any!> id(/*0*/ x: T!): T!
+ public open fun runStatic(/*0*/ r: java.lang.Runnable!): kotlin.Unit
+}
diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall.txt b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall.txt
index 483ad701980..562f0dcd066 100644
--- a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall.txt
+++ b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall.txt
@@ -1,10 +1,10 @@
FILE fqName: fileName:/samConversionInGenericConstructorCall.kt
- FUN name:test1 visibility:public modality:FINAL <> (f:kotlin.Function1) returnType:.C
+ FUN name:test1 visibility:public modality:FINAL <> (f:kotlin.Function1) returnType:.C
VALUE_PARAMETER name:f index:0 type:kotlin.Function1
BLOCK_BODY
- RETURN type=kotlin.Nothing from='public final fun test1 (f: kotlin.Function1): .C declared in '
- CONSTRUCTOR_CALL 'public constructor (jxx: .J.C?, X of .C?>?) declared in .C' type=.C origin=null
- : kotlin.String
+ RETURN type=kotlin.Nothing from='public final fun test1 (f: kotlin.Function1): .C declared in '
+ CONSTRUCTOR_CALL 'public constructor (jxx: .J.C?, X of .C?>?) declared in .C' type=.C origin=null
+ : kotlin.String?
jxx: TYPE_OP type=.J? origin=SAM_CONVERSION typeOperand=.J?
GET_VAR 'f: kotlin.Function1 declared in .test1' type=kotlin.Function1 origin=null
FUN name:test2 visibility:public modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Unit
@@ -14,8 +14,8 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall.kt
TYPE_OP type=kotlin.Function1 origin=CAST typeOperand=kotlin.Function1
GET_VAR 'x: kotlin.Any declared in .test2' type=kotlin.Any origin=null
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
- CONSTRUCTOR_CALL 'public constructor (jxx: .J.C?, X of .C?>?) declared in .C' type=.C origin=null
- : kotlin.String
+ CONSTRUCTOR_CALL 'public constructor (jxx: .J.C?, X of .C?>?) declared in .C' type=.C origin=null
+ : kotlin.String?
jxx: TYPE_OP type=.J? origin=SAM_CONVERSION typeOperand=.J?
TYPE_OP type=kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String?, kotlin.String?> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String?, kotlin.String?>
GET_VAR 'x: kotlin.Any declared in .test2' type=kotlin.Any origin=null
diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.txt b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.txt
index 179be4310da..85358ed52c7 100644
--- a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.txt
+++ b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.txt
@@ -1,13 +1,13 @@
FILE fqName: fileName:/samConversionInGenericConstructorCall_NI.kt
- FUN name:test3 visibility:public modality:FINAL <> (f1:kotlin.Function1, f2:kotlin.Function1) returnType:.C.D
+ FUN name:test3 visibility:public modality:FINAL <> (f1:kotlin.Function1, f2:kotlin.Function1) returnType:.C.D
VALUE_PARAMETER name:f1 index:0 type:kotlin.Function1
VALUE_PARAMETER name:f2 index:1 type:kotlin.Function1
BLOCK_BODY
- RETURN type=kotlin.Nothing from='public final fun test3 (f1: kotlin.Function1, f2: kotlin.Function1):