diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 5a82bbd415d..f692d2f8bb3 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -3120,7 +3120,7 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag @Test public void testAllFilesPresentInAdapted() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/adapted"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/adapted"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true); } @Test @@ -14486,6 +14486,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/inference/nonFunctionalExpectedTypeForLambdaArgument.kt"); } + @Test + @TestMetadata("nothingVsParameterBound.kt") + public void testNothingVsParameterBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -16533,6 +16539,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt34335.kt"); } + @Test + @TestMetadata("kt56448.kt") + public void testKt56448() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt56448.kt"); + } + @Test @TestMetadata("lambdaNothingAndExpectedType.kt") public void testLambdaNothingAndExpectedType() throws Exception { @@ -16587,6 +16599,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/inference/nothingType/reportImplicitNothingOnlyForOwnTypeParameters.kt"); } + @Test + @TestMetadata("selectWithNull.kt") + public void testSelectWithNull() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.kt"); + } + @Test @TestMetadata("specialCallWithMaterializeAndExpectedType.kt") public void testSpecialCallWithMaterializeAndExpectedType() throws Exception { diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot index aaa5ac918e8..402eb7b7de3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.dot @@ -95,14 +95,14 @@ digraph flowFromInplaceLambda2_kt { 29 [label="Enter block"]; 30 [label="Access variable R|/x|"]; 31 [label="Type operator: (R|/x| as R|kotlin/String|)"]; - 32 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 32 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 33 [label="Exit block"]; } 34 [label="Exit function " style="filled" fillcolor=red]; } 35 [label="Postponed exit from lambda"]; - 36 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 37 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 36 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 37 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; 38 [label="Const: Int(1)"]; 39 [label="Postponed enter to lambda"]; subgraph cluster_12 { @@ -179,14 +179,14 @@ digraph flowFromInplaceLambda2_kt { 59 [label="Enter block"]; 60 [label="Access variable R|/x|"]; 61 [label="Type operator: (R|/x| as R|kotlin/String|)"]; - 62 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 62 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 63 [label="Exit block"]; } 64 [label="Exit function " style="filled" fillcolor=red]; } 65 [label="Postponed exit from lambda"]; - 66 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 67 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 66 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 67 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; 68 [label="Const: Int(1)"]; 69 [label="Function call: R|/someCompletedCall|(...)" style="filled" fillcolor=yellow]; 70 [label="Postponed enter to lambda"]; @@ -265,14 +265,14 @@ digraph flowFromInplaceLambda2_kt { 90 [label="Enter block"]; 91 [label="Access variable R|/x|"]; 92 [label="Type operator: (R|/x| as R|kotlin/String|)"]; - 93 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 93 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 94 [label="Exit block"]; } 95 [label="Exit function " style="filled" fillcolor=red]; } 96 [label="Postponed exit from lambda"]; - 97 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 98 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 97 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 98 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; subgraph cluster_24 { color=blue 99 [label="Enter when"]; @@ -430,13 +430,13 @@ digraph flowFromInplaceLambda2_kt { subgraph cluster_41 { color=blue 155 [label="Enter block"]; - 156 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 156 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 157 [label="Exit block"]; } 158 [label="Exit function " style="filled" fillcolor=red]; } 159 [label="Postponed exit from lambda"]; - 160 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 160 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; 161 [label="Exit block"]; } 162 [label="Exit when branch result"]; @@ -453,19 +453,19 @@ digraph flowFromInplaceLambda2_kt { 167 [label="Enter block"]; 168 [label="Const: Null(null)"]; 169 [label="Assignment: R|/p|"]; - 170 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 170 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 171 [label="Exit block"]; } 172 [label="Exit function " style="filled" fillcolor=red]; } 173 [label="Postponed exit from lambda"]; - 174 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 174 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; 175 [label="Exit block"]; } 176 [label="Exit when branch result"]; 177 [label="Exit when"]; } - 178 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 178 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; 179 [label="Const: Int(1)"]; 180 [label="Postponed enter to lambda"]; subgraph cluster_45 { @@ -591,13 +591,13 @@ digraph flowFromInplaceLambda2_kt { 206 [label="Enter block"]; 207 [label="Access variable R|/x|"]; 208 [label="Type operator: (R|/x| as R|kotlin/String|)"]; - 209 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 209 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 210 [label="Exit block"]; } 211 [label="Exit function " style="filled" fillcolor=red]; } 212 [label="Postponed exit from lambda"]; - 213 [label="Function call: $subj$.R|kotlin/let|(...)" style="filled" fillcolor=yellow]; + 213 [label="Function call: $subj$.R|kotlin/let|(...)" style="filled" fillcolor=yellow]; 214 [label="Exit safe call"]; 215 [label="Const: Int(1)"]; 216 [label="Postponed enter to lambda"]; @@ -691,13 +691,13 @@ digraph flowFromInplaceLambda2_kt { 242 [label="Enter block"]; 243 [label="Access variable R|/x|"]; 244 [label="Type operator: (R|/x| as R|kotlin/String|)"]; - 245 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 245 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 246 [label="Exit block"]; } 247 [label="Exit function " style="filled" fillcolor=red]; } 248 [label="Postponed exit from lambda"]; - 249 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 249 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; 250 [label="Exit block"]; } 251 [label="Exit when branch result"]; @@ -714,19 +714,19 @@ digraph flowFromInplaceLambda2_kt { 256 [label="Enter block"]; 257 [label="Access variable R|/x|"]; 258 [label="Type operator: (R|/x| as R|kotlin/String|)"]; - 259 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 259 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 260 [label="Exit block"]; } 261 [label="Exit function " style="filled" fillcolor=red]; } 262 [label="Postponed exit from lambda"]; - 263 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 263 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; 264 [label="Exit block"]; } 265 [label="Exit when branch result"]; 266 [label="Exit when"]; } - 267 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 267 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; 268 [label="Const: Int(1)"]; 269 [label="Postponed enter to lambda"]; subgraph cluster_64 { @@ -849,14 +849,14 @@ digraph flowFromInplaceLambda2_kt { 300 [label="Enter block"]; 301 [label="Const: Null(null)"]; 302 [label="Assignment: R|/p|"]; - 303 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; + 303 [label="Function call: R|/n|()" style="filled" fillcolor=yellow]; 304 [label="Exit block"]; } 305 [label="Exit function " style="filled" fillcolor=red]; } 306 [label="Postponed exit from lambda"]; - 307 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; - 308 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; + 307 [label="Function call: R|kotlin/run|(...)" style="filled" fillcolor=yellow]; + 308 [label="Function call: R|/id|(...)" style="filled" fillcolor=yellow]; 309 [label="Const: Int(1)"]; 310 [label="Postponed enter to lambda"]; subgraph cluster_73 { diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.fir.txt index a81173a7b44..65d823c45f1 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda2.fir.txt @@ -11,9 +11,9 @@ FILE: flowFromInplaceLambda2.kt ^someCompletedCall R|/arg| } public final fun test1(x: R|kotlin/String?|): R|kotlin/Unit| { - R|/foo|(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Nothing?| { + R|/foo|(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Int?| { (R|/x| as R|kotlin/String|) - ^ R|/n|() + ^ R|/n|() } )), Int(1), R|kotlin/run|( = run@fun (): R|kotlin/Int| { R|/x|.R|kotlin/String.length#| @@ -23,9 +23,9 @@ FILE: flowFromInplaceLambda2.kt R|/x|.R|kotlin/String.length| } public final fun test2(x: R|kotlin/String?|): R|kotlin/Unit| { - R|/foo|(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Nothing?| { + R|/foo|(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Int?| { (R|/x| as R|kotlin/String|) - ^ R|/n|() + ^ R|/n|() } )), R|/someCompletedCall|(Int(1)), R|kotlin/run|( = run@fun (): R|kotlin/Int| { R|/x|.R|kotlin/String.length#| @@ -35,9 +35,9 @@ FILE: flowFromInplaceLambda2.kt R|/x|.R|kotlin/String.length| } public final fun test3(x: R|kotlin/String?|): R|kotlin/Unit| { - R|/foo|(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Nothing?| { + R|/foo|(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Int?| { (R|/x| as R|kotlin/String|) - ^ R|/n|() + ^ R|/n|() } )), when () { Boolean(true) -> { @@ -58,17 +58,17 @@ FILE: flowFromInplaceLambda2.kt lvar p: R|kotlin/String?| = R|/x| when () { !=(R|/p|, Null(null)) -> { - R|/foo|(R|/id|(when () { + R|/foo|(R|/id|(when () { Boolean(true) -> { - R|kotlin/run|( = run@fun (): R|kotlin/Nothing?| { + R|kotlin/run|( = run@fun (): R|kotlin/Int?| { R|/p| = Null(null) - ^ R|/n|() + ^ R|/n|() } ) } else -> { - R|kotlin/run|( = run@fun (): R|kotlin/Nothing?| { - ^ R|/n|() + R|kotlin/run|( = run@fun (): R|kotlin/Int?| { + ^ R|/n|() } ) } @@ -84,9 +84,9 @@ FILE: flowFromInplaceLambda2.kt } public final fun test5(x: R|kotlin/String?|, y: R|kotlin/String?|): R|kotlin/Unit| { - R|/foo|(R|/y|?.{ $subj$.R|kotlin/let|( = let@fun (it: R|kotlin/String|): R|kotlin/Nothing?| { + R|/foo|(R|/y|?.{ $subj$.R|kotlin/let|( = let@fun (it: R|kotlin/String|): R|kotlin/String?| { (R|/x| as R|kotlin/String|) - ^ R|/n|() + ^ R|/n|() } ) }, Int(1), R|kotlin/run|( = run@fun (): R|kotlin/String| { ^ String() @@ -95,18 +95,18 @@ FILE: flowFromInplaceLambda2.kt R|/x|.R|kotlin/String.length#| } public final fun test6(x: R|kotlin/String?|): R|kotlin/Unit| { - R|/foo|(R|/id|(when () { + R|/foo|(R|/id|(when () { Boolean(true) -> { - R|kotlin/run|( = run@fun (): R|kotlin/Nothing?| { + R|kotlin/run|( = run@fun (): R|kotlin/Int?| { (R|/x| as R|kotlin/String|) - ^ R|/n|() + ^ R|/n|() } ) } else -> { - R|kotlin/run|( = run@fun (): R|kotlin/Nothing?| { + R|kotlin/run|( = run@fun (): R|kotlin/Int?| { (R|/x| as R|kotlin/String|) - ^ R|/n|() + ^ R|/n|() } ) } @@ -122,9 +122,9 @@ FILE: flowFromInplaceLambda2.kt lvar p: R|kotlin/String?| = R|/x| when () { !=(R|/p|, Null(null)) -> { - R|/foo|(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Nothing?| { + R|/foo|(R|/id|(R|kotlin/run|( = run@fun (): R|kotlin/Int?| { R|/p| = Null(null) - ^ R|/n|() + ^ R|/n|() } )), Int(1), R|kotlin/run|( = run@fun (): R|kotlin/Int| { R|/p|.R|kotlin/String.length#| diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index dfd79536f7e..4991abc2a9d 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -3126,7 +3126,7 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti @Test public void testAllFilesPresentInAdapted() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/adapted"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/adapted"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true); } @Test @@ -14492,6 +14492,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/nonFunctionalExpectedTypeForLambdaArgument.kt"); } + @Test + @TestMetadata("nothingVsParameterBound.kt") + public void testNothingVsParameterBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -16539,6 +16545,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt34335.kt"); } + @Test + @TestMetadata("kt56448.kt") + public void testKt56448() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt56448.kt"); + } + @Test @TestMetadata("lambdaNothingAndExpectedType.kt") public void testLambdaNothingAndExpectedType() throws Exception { @@ -16593,6 +16605,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/nothingType/reportImplicitNothingOnlyForOwnTypeParameters.kt"); } + @Test + @TestMetadata("selectWithNull.kt") + public void testSelectWithNull() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.kt"); + } + @Test @TestMetadata("specialCallWithMaterializeAndExpectedType.kt") public void testSpecialCallWithMaterializeAndExpectedType() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 4502b796581..40946fb6912 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -3120,7 +3120,7 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac @Test public void testAllFilesPresentInAdapted() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/adapted"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/adapted"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true); } @Test @@ -14486,6 +14486,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/nonFunctionalExpectedTypeForLambdaArgument.kt"); } + @Test + @TestMetadata("nothingVsParameterBound.kt") + public void testNothingVsParameterBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -16533,6 +16539,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt34335.kt"); } + @Test + @TestMetadata("kt56448.kt") + public void testKt56448() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt56448.kt"); + } + @Test @TestMetadata("lambdaNothingAndExpectedType.kt") public void testLambdaNothingAndExpectedType() throws Exception { @@ -16587,6 +16599,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/nothingType/reportImplicitNothingOnlyForOwnTypeParameters.kt"); } + @Test + @TestMetadata("selectWithNull.kt") + public void testSelectWithNull() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.kt"); + } + @Test @TestMetadata("specialCallWithMaterializeAndExpectedType.kt") public void testSpecialCallWithMaterializeAndExpectedType() throws Exception { diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt index 3bc2b973d89..5e5395e6219 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt @@ -146,15 +146,39 @@ class ResultTypeResolver( for (constraint in filteredConstraints) { if (!checkConstraint(this, constraint.type, constraint.kind, resultType)) return false } - if (!trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType)) { - if (resultType.isNullableType() && checkSingleLowerNullabilityConstraint(filteredConstraints)) return false - if (isReified(variableWithConstraints.typeVariable)) return false - } - return true + // if resultType is not Nothing + if (trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType)) return true + + // Nothing and Nothing? is not allowed for reified parameters + if (isReified(variableWithConstraints.typeVariable)) return false + + // It's ok to fix result to non-nullable Nothing and parameter is not reified + if (!resultType.isNullableType()) return true + + return isNullableNothingMayBeConsideredAsSuitableResultType(filteredConstraints) } - private fun checkSingleLowerNullabilityConstraint(constraints: List): Boolean { + private fun Context.isNullableNothingMayBeConsideredAsSuitableResultType(constraints: List): Boolean = when { + isK2 -> + // There might be an assertion for green code that if `allUpperConstraintsAreFromBounds(constraints) == true` then + // the single `Nothing?` lower bound constraint has Constraint::isNullabilityConstraint is set to false + // because otherwise we would not start fixing the variable since it has no proper constraints. + allUpperConstraintsAreFromBounds(constraints) + else -> !isThereSingleLowerNullabilityConstraint(constraints) + } + + private fun allUpperConstraintsAreFromBounds(constraints: List): Boolean = + constraints.all { + // Actually, at least for green code that should be an assertion that lower constraints (!isUpper) has `Nothing?` type + // Because otherwise if we had `Nothing? <: T` and `SomethingElse <: T` than it would end with `SomethingElse? <: T` + !it.kind.isUpper() || isFromTypeParameterUpperBound(it) + } + + private fun isFromTypeParameterUpperBound(constraint: Constraint): Boolean = + constraint.position.isFromDeclaredUpperBound || constraint.position.from is DeclaredUpperBoundConstraintPosition<*> + + private fun isThereSingleLowerNullabilityConstraint(constraints: List): Boolean { return constraints.singleOrNull { it.kind.isLower() }?.isNullabilityConstraint ?: false } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt index 1b86011b01a..be56d0df2ad 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintStorage.kt @@ -86,6 +86,10 @@ class Constraint( val position: IncorporationConstraintPosition, val typeHashCode: Int = type.hashCode(), val derivedFrom: Set, + // This value is true for constraints of the form `Nothing? <: Tv` + // that have been created during incorporation phase of the constraint of the form `Kv? <: Tv` (where `Kv` another type variable). + // The main idea behind that parameter is that we don't consider such constraints as proper (signifying that variable is ready for completion). + // And also, there is additional logic in K1 that doesn't allow to fix variable into `Nothing?` if we had only that kind of lower constraints val isNullabilityConstraint: Boolean, val inputTypePositionBeforeIncorporation: OnlyInputTypeConstraintPosition? = null ) { diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/kt56448.fir.kt b/compiler/testData/diagnostics/tests/inference/nothingType/kt56448.fir.kt new file mode 100644 index 00000000000..c64a0a64a5f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/kt56448.fir.kt @@ -0,0 +1,43 @@ +// SKIP_TXT +// WITH_STDLIB +// ISSUE: KT-56448 +// FILE: SomeJavaClass.java + +public class SomeJavaClass { + public static String getString() { + return ""; + } +} + +// FILE: main.kt +import kotlin.reflect.KProperty1 + +interface XdEntity +class XdIssue : XdEntity { + val isRemoved: Boolean = true + var votes: Int = 0 +} + +fun getNullableIssue(): XdIssue? = null + +fun CharSequence.toXd(): T = null!! + +fun XdIssue.duplicatesRootSearch(): XdIssue = this +fun ?> T.getOldValue(property: KProperty1): R? = null + +internal fun updateVotesForDuplicates(issue: XdIssue) { + val toRecount = HashSet() + var oldDup = getNullableIssue() + if (oldDup != null) { + oldDup = try { + SomeJavaClass.getString().toXd() + } catch (_: Exception) { + null + } + } + val newDup = getNullableIssue() + + if (oldDup != null && !oldDup.isRemoved) { + toRecount.add(oldDup.duplicatesRootSearch()) + } +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/kt56448.kt b/compiler/testData/diagnostics/tests/inference/nothingType/kt56448.kt new file mode 100644 index 00000000000..428bd22707e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/kt56448.kt @@ -0,0 +1,43 @@ +// SKIP_TXT +// WITH_STDLIB +// ISSUE: KT-56448 +// FILE: SomeJavaClass.java + +public class SomeJavaClass { + public static String getString() { + return ""; + } +} + +// FILE: main.kt +import kotlin.reflect.KProperty1 + +interface XdEntity +class XdIssue : XdEntity { + val isRemoved: Boolean = true + var votes: Int = 0 +} + +fun getNullableIssue(): XdIssue? = null + +fun CharSequence.toXd(): T = null!! + +fun XdIssue.duplicatesRootSearch(): XdIssue = this +fun ?> T.getOldValue(property: KProperty1): R? = null + +internal fun updateVotesForDuplicates(issue: XdIssue) { + val toRecount = HashSet() + var oldDup = getNullableIssue() + if (oldDup != null) { + oldDup = try { + SomeJavaClass.getString().toXd() + } catch (_: Exception) { + null + } + } + val newDup = getNullableIssue() + + if (oldDup != null && !oldDup.isRemoved) { + toRecount.add(oldDup.duplicatesRootSearch()) + } +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.fir.kt b/compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.fir.kt new file mode 100644 index 00000000000..b5eb71d1221 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.fir.kt @@ -0,0 +1,13 @@ +// SKIP_TXT +// ISSUE: KT-55691 + +fun materialize(): T = TODO() +fun select(x: S, y: S): S = x + +fun main() { + // materialize's type argument is inferred to `Nothing?` in K1 and `String?` in K2 + val x: String? = select(materialize(), null) + + // materialize's type argument is inferred to `Nothing?` both in K1 and K2 + select(materialize(), null) +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.kt b/compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.kt new file mode 100644 index 00000000000..fa1bc9de69b --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.kt @@ -0,0 +1,13 @@ +// SKIP_TXT +// ISSUE: KT-55691 + +fun materialize(): T = TODO() +fun select(x: S, y: S): S = x + +fun main() { + // materialize's type argument is inferred to `Nothing?` in K1 and `String?` in K2 + val x: String? = select(materialize(), null) + + // materialize's type argument is inferred to `Nothing?` both in K1 and K2 + select(materialize(), null) +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/specialCallWithMaterializeAndExpectedType.fir.kt b/compiler/testData/diagnostics/tests/inference/nothingType/specialCallWithMaterializeAndExpectedType.fir.kt deleted file mode 100644 index 21c46587a59..00000000000 --- a/compiler/testData/diagnostics/tests/inference/nothingType/specialCallWithMaterializeAndExpectedType.fir.kt +++ /dev/null @@ -1,7 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_VARIABLE - -fun foo() { - val s: String? = if (true) materialize() else null -} - -fun materialize(): K = TODO() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/specialCallWithMaterializeAndExpectedType.kt b/compiler/testData/diagnostics/tests/inference/nothingType/specialCallWithMaterializeAndExpectedType.kt index e52674c522d..57c9839179b 100644 --- a/compiler/testData/diagnostics/tests/inference/nothingType/specialCallWithMaterializeAndExpectedType.kt +++ b/compiler/testData/diagnostics/tests/inference/nothingType/specialCallWithMaterializeAndExpectedType.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE fun foo() { diff --git a/compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt b/compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt new file mode 100644 index 00000000000..9879765a612 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt @@ -0,0 +1,15 @@ +// FIR_IDENTICAL +// SKIP_TXT + +class Out(val t: T) + +fun foo() { + // We have two constraints here: + // Nothing? <: T (from argument `null` type) + // T <: CharSequence? + // And we fix T to `Nothing?`, because it's still more preferrable than constraint from the upper bound + val x1 = Out(null) + bar(")!>x1) +} + +fun bar(w: Out) {} diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/exactAnnotationWithUpperBoundConstraint.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/exactAnnotationWithUpperBoundConstraint.fir.kt index d936e59ecdd..41456ee2e5f 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/exactAnnotationWithUpperBoundConstraint.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/exactAnnotationWithUpperBoundConstraint.fir.kt @@ -8,7 +8,7 @@ fun test() { val map: Map = mapOf("x" to 1) val r1 = map.getOrDefault_Exact("y", null) - r1 + r1 val r2 = map.getOrDefault_Exact("y", null as Int?) r2 diff --git a/compiler/testData/ir/irText/declarations/kt47527.fir.ir.txt b/compiler/testData/ir/irText/declarations/kt47527.fir.ir.txt index a8036c99e8f..697ddeff7c2 100644 --- a/compiler/testData/ir/irText/declarations/kt47527.fir.ir.txt +++ b/compiler/testData/ir/irText/declarations/kt47527.fir.ir.txt @@ -28,12 +28,12 @@ FILE fqName: fileName:/kt47527.kt VALUE_PARAMETER name:value index:0 type:kotlin.Any? BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test_2 (value: kotlin.Any?): kotlin.String? declared in ' - CALL 'public final fun run (block: kotlin.Function0): R of kotlin.StandardKt.run [inline] declared in kotlin.StandardKt' type=kotlin.Nothing? origin=null - : kotlin.Nothing? - block: FUN_EXPR type=kotlin.Function0 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Nothing? + CALL 'public final fun run (block: kotlin.Function0): R of kotlin.StandardKt.run [inline] declared in kotlin.StandardKt' type=kotlin.String? origin=null + : kotlin.String? + block: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String? BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlin.Nothing? declared in .test_2' + RETURN type=kotlin.Nothing from='local final fun (): kotlin.String? declared in .test_2' BLOCK type=kotlin.Nothing? origin=SAFE_CALL VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Any? [val] GET_VAR 'value: kotlin.Any? declared in .test_2' type=kotlin.Any? origin=null diff --git a/compiler/testData/ir/irText/declarations/kt47527.fir.kt.txt b/compiler/testData/ir/irText/declarations/kt47527.fir.kt.txt index cb0a540c889..70c5491e71a 100644 --- a/compiler/testData/ir/irText/declarations/kt47527.fir.kt.txt +++ b/compiler/testData/ir/irText/declarations/kt47527.fir.kt.txt @@ -12,7 +12,7 @@ fun test_1(value: Any?): String? { } fun test_2(value: Any?): String? { - return run(block = local fun (): Nothing? { + return run(block = local fun (): String? { return { // BLOCK val tmp1_safe_receiver: Any? = value when { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 9ca733aabfa..0487a3f7c91 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -3126,7 +3126,7 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { @Test public void testAllFilesPresentInAdapted() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/adapted"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/adapted"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true); } @Test @@ -14492,6 +14492,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/nonFunctionalExpectedTypeForLambdaArgument.kt"); } + @Test + @TestMetadata("nothingVsParameterBound.kt") + public void testNothingVsParameterBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -16539,6 +16545,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt34335.kt"); } + @Test + @TestMetadata("kt56448.kt") + public void testKt56448() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt56448.kt"); + } + @Test @TestMetadata("lambdaNothingAndExpectedType.kt") public void testLambdaNothingAndExpectedType() throws Exception { @@ -16593,6 +16605,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/nothingType/reportImplicitNothingOnlyForOwnTypeParameters.kt"); } + @Test + @TestMetadata("selectWithNull.kt") + public void testSelectWithNull() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/selectWithNull.kt"); + } + @Test @TestMetadata("specialCallWithMaterializeAndExpectedType.kt") public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {