From a0a57581ecd974aef13094b1c76d705d1c6b0d3d Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Wed, 20 Oct 2021 10:06:46 +0300 Subject: [PATCH] FIR: Do not add alias for variables with explicit type --- ...CompilerTestFE10TestdataTestGenerated.java | 6 + .../boundSmartcastsInBranches.dot | 319 +++++++++++++++++- .../boundSmartcastsInBranches.fir.txt | 54 +++ .../boundSmartcastsInBranches.kt | 42 +++ .../resolve/whenExpressionType.fir.txt | 4 +- .../testData/resolve/whenExpressionType.kt | 4 +- ...irOldFrontendDiagnosticsTestGenerated.java | 6 + ...DiagnosticsWithLightTreeTestGenerated.java | 6 + .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 11 +- .../FirDeclarationsResolveTransformer.kt | 5 +- .../equalsNaN_properIeeeComparisons.kt | 3 +- .../diagnostics/tests/Variance.fir.kt | 6 +- .../dataFlow/assignment/assignToNewVal.fir.kt | 4 +- .../tests/enum/enumSubjectTypeCheck.fir.kt | 4 +- .../generics/projectionsScope/kt7296.fir.kt | 2 +- .../generics/suppressVarianceConflict.fir.kt | 17 - .../generics/suppressVarianceConflict.kt | 1 + ...ectedWithGenericsInDifferentPackage.fir.kt | 8 +- .../tests/smartCasts/level_1_0.fir.kt | 2 +- .../tests/smartCasts/toInvisible.fir.kt | 44 +++ .../tests/smartCasts/toInvisible.kt | 45 +++ .../variables/whileWithBreak.fir.kt | 2 +- .../varnotnull/boundInitializer.fir.kt | 2 +- .../whenSmartCastToEnum.fir.ir.txt | 6 +- .../whenSmartCastToEnum.fir.kt.txt | 4 +- .../ir/irText/firProblems/JCTree.fir.ir.txt | 6 +- .../ir/irText/firProblems/JCTree.fir.kt.txt | 2 +- .../test/runners/DiagnosticTestGenerated.java | 6 + .../diagnostics/notLinked/dfa/pos/58.fir.kt | 8 +- 29 files changed, 562 insertions(+), 67 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.fir.kt create mode 100644 compiler/testData/diagnostics/tests/smartCasts/toInvisible.fir.kt create mode 100644 compiler/testData/diagnostics/tests/smartCasts/toInvisible.kt 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 1a9b442efbc..0d5ca0223d5 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 @@ -27495,6 +27495,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/smartCasts/throwInTry.kt"); } + @Test + @TestMetadata("toInvisible.kt") + public void testToInvisible() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/toInvisible.kt"); + } + @Test @TestMetadata("twoImplicitReceivers.kt") public void testTwoImplicitReceivers() throws Exception { diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot index 32caefb2c78..d32a8f5f26f 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.dot @@ -592,9 +592,9 @@ digraph boundSmartcastsInBranches_kt { 219 [label="Access variable R|/x|"]; 220 [label="Access variable R|kotlin/String.length|"]; 221 [label="Access variable R|/y|"]; - 222 [label="Access variable R|kotlin/String.length|"]; + 222 [label="Access variable #"]; 223 [label="Access variable R|/z|"]; - 224 [label="Access variable R|kotlin/String.length|"]; + 224 [label="Access variable #"]; 225 [label="Exit block"]; } 226 [label="Exit when branch result"]; @@ -617,11 +617,11 @@ digraph boundSmartcastsInBranches_kt { color=blue 236 [label="Enter block"]; 237 [label="Access variable R|/x|"]; - 238 [label="Access variable R|kotlin/String.length|"]; + 238 [label="Access variable #"]; 239 [label="Access variable R|/y|"]; 240 [label="Access variable R|kotlin/String.length|"]; 241 [label="Access variable R|/z|"]; - 242 [label="Access variable R|kotlin/String.length|"]; + 242 [label="Access variable #"]; 243 [label="Exit block"]; } 244 [label="Exit when branch result"]; @@ -644,9 +644,9 @@ digraph boundSmartcastsInBranches_kt { color=blue 254 [label="Enter block"]; 255 [label="Access variable R|/x|"]; - 256 [label="Access variable R|kotlin/String.length|"]; + 256 [label="Access variable #"]; 257 [label="Access variable R|/y|"]; - 258 [label="Access variable R|kotlin/String.length|"]; + 258 [label="Access variable #"]; 259 [label="Access variable R|/z|"]; 260 [label="Access variable R|kotlin/String.length|"]; 261 [label="Exit block"]; @@ -677,7 +677,7 @@ digraph boundSmartcastsInBranches_kt { 277 [label="Access variable R|/y|"]; 278 [label="Access variable #"]; 279 [label="Access variable R|/z|"]; - 280 [label="Access variable R|kotlin/String.length|"]; + 280 [label="Access variable #"]; 281 [label="Exit block"]; } 282 [label="Exit when branch result"]; @@ -728,7 +728,7 @@ digraph boundSmartcastsInBranches_kt { color=blue 311 [label="Enter block"]; 312 [label="Access variable R|/x|"]; - 313 [label="Access variable R|kotlin/String.length|"]; + 313 [label="Access variable #"]; 314 [label="Access variable R|/y|"]; 315 [label="Access variable #"]; 316 [label="Access variable R|/z|"]; @@ -864,4 +864,307 @@ digraph boundSmartcastsInBranches_kt { 320 -> {321}; 321 -> {322}; + subgraph cluster_70 { + color=red + 323 [label="Enter function test_8" style="filled" fillcolor=red]; + subgraph cluster_71 { + color=blue + 324 [label="Enter block"]; + 325 [label="Const: Null(null)"]; + 326 [label="Variable declaration: lval z: R|kotlin/String?|"]; + 327 [label="Access variable R|/z|"]; + 328 [label="Variable declaration: lvar y: R|kotlin/String?|"]; + 329 [label="Access variable R|/y|"]; + 330 [label="Variable declaration: lval x: R|kotlin/String?|"]; + subgraph cluster_72 { + color=blue + 331 [label="Enter when"]; + subgraph cluster_73 { + color=blue + 332 [label="Enter when branch condition "]; + 333 [label="Access variable R|/x|"]; + 334 [label="Const: Null(null)"]; + 335 [label="Equality operator !="]; + 336 [label="Exit when branch condition"]; + } + 337 [label="Synthetic else branch"]; + 338 [label="Enter when branch result"]; + subgraph cluster_74 { + color=blue + 339 [label="Enter block"]; + 340 [label="Access variable R|/x|"]; + 341 [label="Access variable R|kotlin/String.length|"]; + 342 [label="Access variable R|/y|"]; + 343 [label="Access variable R|kotlin/String.length|"]; + 344 [label="Access variable R|/z|"]; + 345 [label="Access variable R|kotlin/String.length|"]; + 346 [label="Exit block"]; + } + 347 [label="Exit when branch result"]; + 348 [label="Exit when"]; + } + subgraph cluster_75 { + color=blue + 349 [label="Enter when"]; + subgraph cluster_76 { + color=blue + 350 [label="Enter when branch condition "]; + 351 [label="Access variable R|/y|"]; + 352 [label="Const: Null(null)"]; + 353 [label="Equality operator !="]; + 354 [label="Exit when branch condition"]; + } + 355 [label="Synthetic else branch"]; + 356 [label="Enter when branch result"]; + subgraph cluster_77 { + color=blue + 357 [label="Enter block"]; + 358 [label="Access variable R|/x|"]; + 359 [label="Access variable R|kotlin/String.length|"]; + 360 [label="Access variable R|/y|"]; + 361 [label="Access variable R|kotlin/String.length|"]; + 362 [label="Access variable R|/z|"]; + 363 [label="Access variable R|kotlin/String.length|"]; + 364 [label="Exit block"]; + } + 365 [label="Exit when branch result"]; + 366 [label="Exit when"]; + } + subgraph cluster_78 { + color=blue + 367 [label="Enter when"]; + subgraph cluster_79 { + color=blue + 368 [label="Enter when branch condition "]; + 369 [label="Access variable R|/z|"]; + 370 [label="Const: Null(null)"]; + 371 [label="Equality operator !="]; + 372 [label="Exit when branch condition"]; + } + 373 [label="Synthetic else branch"]; + 374 [label="Enter when branch result"]; + subgraph cluster_80 { + color=blue + 375 [label="Enter block"]; + 376 [label="Access variable R|/x|"]; + 377 [label="Access variable R|kotlin/String.length|"]; + 378 [label="Access variable R|/y|"]; + 379 [label="Access variable R|kotlin/String.length|"]; + 380 [label="Access variable R|/z|"]; + 381 [label="Access variable R|kotlin/String.length|"]; + 382 [label="Exit block"]; + } + 383 [label="Exit when branch result"]; + 384 [label="Exit when"]; + } + 385 [label="Const: Null(null)"]; + 386 [label="Assignment: R|/y|"]; + subgraph cluster_81 { + color=blue + 387 [label="Enter when"]; + subgraph cluster_82 { + color=blue + 388 [label="Enter when branch condition "]; + 389 [label="Access variable R|/x|"]; + 390 [label="Const: Null(null)"]; + 391 [label="Equality operator !="]; + 392 [label="Exit when branch condition"]; + } + 393 [label="Synthetic else branch"]; + 394 [label="Enter when branch result"]; + subgraph cluster_83 { + color=blue + 395 [label="Enter block"]; + 396 [label="Access variable R|/x|"]; + 397 [label="Access variable R|kotlin/String.length|"]; + 398 [label="Access variable R|/y|"]; + 399 [label="Access variable #"]; + 400 [label="Access variable R|/z|"]; + 401 [label="Access variable R|kotlin/String.length|"]; + 402 [label="Exit block"]; + } + 403 [label="Exit when branch result"]; + 404 [label="Exit when"]; + } + subgraph cluster_84 { + color=blue + 405 [label="Enter when"]; + subgraph cluster_85 { + color=blue + 406 [label="Enter when branch condition "]; + 407 [label="Access variable R|/y|"]; + 408 [label="Const: Null(null)"]; + 409 [label="Equality operator !="]; + 410 [label="Exit when branch condition"]; + } + 411 [label="Synthetic else branch"]; + 412 [label="Enter when branch result"]; + subgraph cluster_86 { + color=blue + 413 [label="Enter block"]; + 414 [label="Access variable R|/x|"]; + 415 [label="Access variable #"]; + 416 [label="Access variable R|/y|"]; + 417 [label="Stub" style="filled" fillcolor=gray]; + 418 [label="Access variable R|kotlin/String.length|" style="filled" fillcolor=gray]; + 419 [label="Access variable R|/z|" style="filled" fillcolor=gray]; + 420 [label="Access variable #" style="filled" fillcolor=gray]; + 421 [label="Exit block" style="filled" fillcolor=gray]; + } + 422 [label="Exit when branch result" style="filled" fillcolor=gray]; + 423 [label="Exit when"]; + } + subgraph cluster_87 { + color=blue + 424 [label="Enter when"]; + subgraph cluster_88 { + color=blue + 425 [label="Enter when branch condition "]; + 426 [label="Access variable R|/z|"]; + 427 [label="Const: Null(null)"]; + 428 [label="Equality operator !="]; + 429 [label="Exit when branch condition"]; + } + 430 [label="Synthetic else branch"]; + 431 [label="Enter when branch result"]; + subgraph cluster_89 { + color=blue + 432 [label="Enter block"]; + 433 [label="Access variable R|/x|"]; + 434 [label="Access variable R|kotlin/String.length|"]; + 435 [label="Access variable R|/y|"]; + 436 [label="Access variable #"]; + 437 [label="Access variable R|/z|"]; + 438 [label="Access variable R|kotlin/String.length|"]; + 439 [label="Exit block"]; + } + 440 [label="Exit when branch result"]; + 441 [label="Exit when"]; + } + 442 [label="Exit block"]; + } + 443 [label="Exit function test_8" style="filled" fillcolor=red]; + } + 323 -> {324}; + 324 -> {325}; + 325 -> {326}; + 326 -> {327}; + 327 -> {328}; + 328 -> {329}; + 329 -> {330}; + 330 -> {331}; + 331 -> {332}; + 332 -> {333}; + 333 -> {334}; + 334 -> {335}; + 335 -> {336}; + 336 -> {338 337}; + 337 -> {348}; + 338 -> {339}; + 339 -> {340}; + 340 -> {341}; + 341 -> {342}; + 342 -> {343}; + 343 -> {344}; + 344 -> {345}; + 345 -> {346}; + 346 -> {347}; + 347 -> {348}; + 348 -> {349}; + 349 -> {350}; + 350 -> {351}; + 351 -> {352}; + 352 -> {353}; + 353 -> {354}; + 354 -> {356 355}; + 355 -> {366}; + 356 -> {357}; + 357 -> {358}; + 358 -> {359}; + 359 -> {360}; + 360 -> {361}; + 361 -> {362}; + 362 -> {363}; + 363 -> {364}; + 364 -> {365}; + 365 -> {366}; + 366 -> {367}; + 367 -> {368}; + 368 -> {369}; + 369 -> {370}; + 370 -> {371}; + 371 -> {372}; + 372 -> {374 373}; + 373 -> {384}; + 374 -> {375}; + 375 -> {376}; + 376 -> {377}; + 377 -> {378}; + 378 -> {379}; + 379 -> {380}; + 380 -> {381}; + 381 -> {382}; + 382 -> {383}; + 383 -> {384}; + 384 -> {385}; + 385 -> {386}; + 386 -> {387}; + 387 -> {388}; + 388 -> {389}; + 389 -> {390}; + 390 -> {391}; + 391 -> {392}; + 392 -> {394 393}; + 393 -> {404}; + 394 -> {395}; + 395 -> {396}; + 396 -> {397}; + 397 -> {398}; + 398 -> {399}; + 399 -> {400}; + 400 -> {401}; + 401 -> {402}; + 402 -> {403}; + 403 -> {404}; + 404 -> {405}; + 405 -> {406}; + 406 -> {407}; + 407 -> {408}; + 408 -> {409}; + 409 -> {410}; + 410 -> {412 411}; + 411 -> {423}; + 412 -> {413}; + 413 -> {414}; + 414 -> {415}; + 415 -> {416}; + 416 -> {443} [label=onUncaughtException]; + 416 -> {417} [style=dotted]; + 417 -> {418} [style=dotted]; + 418 -> {419} [style=dotted]; + 419 -> {420} [style=dotted]; + 420 -> {421} [style=dotted]; + 421 -> {422} [style=dotted]; + 422 -> {423} [style=dotted]; + 423 -> {424}; + 424 -> {425}; + 425 -> {426}; + 426 -> {427}; + 427 -> {428}; + 428 -> {429}; + 429 -> {431 430}; + 430 -> {441}; + 431 -> {432}; + 432 -> {433}; + 433 -> {434}; + 434 -> {435}; + 435 -> {436}; + 436 -> {437}; + 437 -> {438}; + 438 -> {439}; + 439 -> {440}; + 440 -> {441}; + 441 -> {442}; + 442 -> {443}; + } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.fir.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.fir.txt index 4e8860ea5f9..b35e59e68ac 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.fir.txt @@ -104,6 +104,60 @@ FILE: boundSmartcastsInBranches.kt R|/x|.R|/A.s| } public final fun test_7(): R|kotlin/Unit| { + lval z: R|kotlin/String?| = Null(null) + lvar y: R|kotlin/String?| = R|/z| + lval x: R|kotlin/String?| = R|/y| + when () { + !=(R|/x|, Null(null)) -> { + R|/x|.R|kotlin/String.length| + R|/y|.# + R|/z|.# + } + } + + when () { + !=(R|/y|, Null(null)) -> { + R|/x|.# + R|/y|.R|kotlin/String.length| + R|/z|.# + } + } + + when () { + !=(R|/z|, Null(null)) -> { + R|/x|.# + R|/y|.# + R|/z|.R|kotlin/String.length| + } + } + + R|/y| = Null(null) + when () { + !=(R|/x|, Null(null)) -> { + R|/x|.R|kotlin/String.length| + R|/y|.# + R|/z|.# + } + } + + when () { + !=(R|/y|, Null(null)) -> { + R|/x|.# + R|/y|.R|kotlin/String.length| + R|/z|.# + } + } + + when () { + !=(R|/z|, Null(null)) -> { + R|/x|.# + R|/y|.# + R|/z|.R|kotlin/String.length| + } + } + + } + public final fun test_8(): R|kotlin/Unit| { lval z: R|kotlin/String?| = Null(null) lvar y: R|kotlin/String?| = R|/z| lval x: R|kotlin/String?| = R|/y| diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.kt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.kt index 3f6f10b70a8..982a3305896 100644 --- a/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.kt +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/boundSmartcasts/boundSmartcastsInBranches.kt @@ -83,6 +83,48 @@ fun test_7() { var y : String? = z val x: String? = y + if (x != null) { + x.length // OK + y.length // Bad + z.length // Bad + } + if (y != null) { + x.length // Bad + y.length // OK + z.length // Bad + } + + if (z != null) { + x.length // Bad + y.length // Bad + z.length // OK + } + + y = null + + if (x != null) { + x.length // OK + y.length // Bad + z.length // Bad + } + if (y != null) { + x.length // Bad + y.length // OK + z.length // Bad + } + + if (z != null) { + x.length // Bad + y.length // Bad + z.length // OK + } +} + +fun test_8() { + val z: String? = null + var y = z + val x = y + if (x != null) { x.length // OK y.length // OK diff --git a/compiler/fir/analysis-tests/testData/resolve/whenExpressionType.fir.txt b/compiler/fir/analysis-tests/testData/resolve/whenExpressionType.fir.txt index e08136acf00..de9317e96eb 100644 --- a/compiler/fir/analysis-tests/testData/resolve/whenExpressionType.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/whenExpressionType.fir.txt @@ -146,7 +146,7 @@ FILE: whenExpressionType.kt } public final fun case9(): R|kotlin/Unit| { lval flag: R|kotlin/Any| = Q|A|.R|/A.A1| - lval l1: R|B| = when (R|/flag|) { + lval l1: R|kotlin/Unit| = when (R|/flag|) { ==($subj$, Q|A|.R|/A.A1|) -> { R|/B.B|() } @@ -155,5 +155,5 @@ FILE: whenExpressionType.kt } } - lval x1: R|C| = R|/C.C|(R|/l1|) + lval x1: R|C| = #(R|/l1|) } diff --git a/compiler/fir/analysis-tests/testData/resolve/whenExpressionType.kt b/compiler/fir/analysis-tests/testData/resolve/whenExpressionType.kt index b4944831f8e..98392d64a6b 100644 --- a/compiler/fir/analysis-tests/testData/resolve/whenExpressionType.kt +++ b/compiler/fir/analysis-tests/testData/resolve/whenExpressionType.kt @@ -102,10 +102,10 @@ fun case8() { // TESTCASE NUMBER: 9 fun case9() { val flag: Any = A.A1 - val l1 = when (flag) { + val l1 = when (flag) { A.A1 -> B() A.A2 -> B() } - val x1 = C(l1) + val x1 = C(l1) } 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 b51a65c1e78..f5cc8a5fdc3 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 @@ -27495,6 +27495,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/smartCasts/throwInTry.kt"); } + @Test + @TestMetadata("toInvisible.kt") + public void testToInvisible() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/toInvisible.kt"); + } + @Test @TestMetadata("twoImplicitReceivers.kt") public void testTwoImplicitReceivers() 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 cc1e673b345..c4c0fa00762 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 @@ -27495,6 +27495,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/smartCasts/throwInTry.kt"); } + @Test + @TestMetadata("toInvisible.kt") + public void testToInvisible() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/toInvisible.kt"); + } + @Test @TestMetadata("twoImplicitReceivers.kt") public void testTwoImplicitReceivers() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index 9f93b8b91d2..61d7e429ac5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -1068,10 +1068,10 @@ abstract class FirDataFlowAnalyzer( graphBuilder.exitConstExpression(constExpression).mergeIncomingFlow() } - fun exitLocalVariableDeclaration(variable: FirProperty) { + fun exitLocalVariableDeclaration(variable: FirProperty, hadExplicitType: Boolean) { val node = graphBuilder.exitVariableDeclaration(variable).mergeIncomingFlow() val initializer = variable.initializer ?: return - exitVariableInitialization(node, initializer, variable, assignment = null) + exitVariableInitialization(node, initializer, variable, assignment = null, hadExplicitType) } fun exitVariableAssignment(assignment: FirVariableAssignment) { @@ -1079,7 +1079,7 @@ abstract class FirDataFlowAnalyzer( val property = (assignment.lValue as? FirResolvedNamedReference)?.resolvedSymbol?.fir as? FirProperty ?: return // TODO: add unstable smartcast if (property.isLocal || !property.isVar) { - exitVariableInitialization(node, assignment.rValue, property, assignment) + exitVariableInitialization(node, assignment.rValue, property, assignment, hasExplicitType = false) } processConditionalContract(assignment) } @@ -1088,7 +1088,8 @@ abstract class FirDataFlowAnalyzer( node: CFGNode<*>, initializer: FirExpression, property: FirProperty, - assignment: FirVariableAssignment? + assignment: FirVariableAssignment?, + hasExplicitType: Boolean, ) { val flow = node.flow val propertyVariable = variableStorage.getOrCreateRealVariableWithoutUnwrappingAlias( @@ -1109,7 +1110,7 @@ abstract class FirDataFlowAnalyzer( val isInitializerStable = initializerVariable.isStable || (initializerVariable.hasLocalStability && initializer.isAccessToStableVariable()) - if (isInitializerStable && (propertyVariable.hasLocalStability || propertyVariable.isStable)) { + if (!hasExplicitType && isInitializerStable && (propertyVariable.hasLocalStability || propertyVariable.isStable)) { logicSystem.addLocalVariableAlias( flow, propertyVariable, RealVariableAndType(initializerVariable, initializer.coneType) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 41426236413..fa7fcd11c6f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -307,6 +307,9 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor assert(variable.isLocal) variable.transformDelegate(transformer, ResolutionMode.ContextDependentDelegate) val delegate = variable.delegate + + val hadExplicitType = variable.returnTypeRef !is FirImplicitTypeRef + if (delegate != null) { transformPropertyAccessorsWithDelegate(variable, delegate) if (variable.delegateFieldSymbol != null) { @@ -326,7 +329,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor } variable.transformOtherChildren(transformer, ResolutionMode.ContextIndependent) context.storeVariable(variable) - dataFlowAnalyzer.exitLocalVariableDeclaration(variable) + dataFlowAnalyzer.exitLocalVariableDeclaration(variable, hadExplicitType) return variable } diff --git a/compiler/testData/codegen/box/ieee754/equalsNaN_properIeeeComparisons.kt b/compiler/testData/codegen/box/ieee754/equalsNaN_properIeeeComparisons.kt index 5a7499cebcb..d1356c38ecc 100644 --- a/compiler/testData/codegen/box/ieee754/equalsNaN_properIeeeComparisons.kt +++ b/compiler/testData/codegen/box/ieee754/equalsNaN_properIeeeComparisons.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +ProperIeee754Comparisons -// IGNORE_BACKEND_FIR: JVM_IR // WITH_RUNTIME import kotlin.test.* @@ -224,4 +223,4 @@ fun box(): String { testFloat(Float.NaN, Float.NaN, Float.NaN) return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/Variance.fir.kt b/compiler/testData/diagnostics/tests/Variance.fir.kt index aede7126fba..1960030c3a6 100644 --- a/compiler/testData/diagnostics/tests/Variance.fir.kt +++ b/compiler/testData/diagnostics/tests/Variance.fir.kt @@ -11,10 +11,10 @@ fun foo(c: Consumer, p: Producer, u: Usual) { val c2: Consumer = c1 val p1: Producer = p - val p2: Producer = p1 + val p2: Producer = p1 val u1: Usual = u - val u2: Usual = u1 + val u2: Usual = u1 } //Arrays copy example @@ -37,4 +37,4 @@ fun f(ints: Array, any: Array, numbers: Array) { copy2(ints, numbers) copy3(ints, numbers) copy4(ints, numbers) //ok -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/dataFlow/assignment/assignToNewVal.fir.kt b/compiler/testData/diagnostics/tests/dataFlow/assignment/assignToNewVal.fir.kt index 8db26209994..67107594810 100644 --- a/compiler/testData/diagnostics/tests/dataFlow/assignment/assignToNewVal.fir.kt +++ b/compiler/testData/diagnostics/tests/dataFlow/assignment/assignToNewVal.fir.kt @@ -6,5 +6,5 @@ fun test(a: Any?) { b.hashCode() val c: Any? = a - c.hashCode() -} \ No newline at end of file + c.hashCode() +} diff --git a/compiler/testData/diagnostics/tests/enum/enumSubjectTypeCheck.fir.kt b/compiler/testData/diagnostics/tests/enum/enumSubjectTypeCheck.fir.kt index de45682c62d..e0fbbec1a88 100644 --- a/compiler/testData/diagnostics/tests/enum/enumSubjectTypeCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/enumSubjectTypeCheck.fir.kt @@ -5,7 +5,7 @@ enum class En { A, B, ะก } fun foo() { // nullable variable val en2: Any? = En.A - if (en2 is En) { + if (en2 is En) { when (en2) { En.A -> {} En.B -> {} @@ -15,7 +15,7 @@ fun foo() { // not nullable variable val en1: Any = En.A - if (en1 is En) { + if (en1 is En) { when (en1) { En.A -> {} En.B -> {} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.fir.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.fir.kt index 510ab6b0378..367b1c87d24 100644 --- a/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.fir.kt @@ -10,5 +10,5 @@ fun main() { val c : ListOfLists<*> = b val d : ArrayList> = c.x - c.x checkType { _>>() } + c.x checkType { _>>() } } diff --git a/compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.fir.kt b/compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.fir.kt deleted file mode 100644 index 3a491b04dd4..00000000000 --- a/compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE - -class A { - fun foo(x: @UnsafeVariance T) {} - fun foo(x: @UnsafeVariance T, y: List<@UnsafeVariance T>): @UnsafeVariance E = null!! - - fun bar(): List<@UnsafeVariance E> = null!! -} - -fun foo(x: A, cs: CharSequence, ls: List) { - val y: A = x - - y.foo(cs) - val s: String = y.foo(cs, ls) - - val ls2: List = y.bar() -} diff --git a/compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.kt b/compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.kt index 553af5275bc..bff4d9948cb 100644 --- a/compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.kt +++ b/compiler/testData/diagnostics/tests/generics/suppressVarianceConflict.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE class A { diff --git a/compiler/testData/diagnostics/tests/protectedWithGenericsInDifferentPackage.fir.kt b/compiler/testData/diagnostics/tests/protectedWithGenericsInDifferentPackage.fir.kt index af2e80afaac..1d7c21f60f2 100644 --- a/compiler/testData/diagnostics/tests/protectedWithGenericsInDifferentPackage.fir.kt +++ b/compiler/testData/diagnostics/tests/protectedWithGenericsInDifferentPackage.fir.kt @@ -32,10 +32,10 @@ fun test(s: bar.Sub) { s.doSomething() s.doSomething2() val s2: Super = s - s2.name - s2.name = "" + s2.name + s2.name = "" s2.name2 - s2.name2 = "" - s2.doSomething() + s2.name2 = "" + s2.doSomething() s2.doSomething2() } diff --git a/compiler/testData/diagnostics/tests/smartCasts/level_1_0.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/level_1_0.fir.kt index 11da125a2b8..b77282ddb4b 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/level_1_0.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/level_1_0.fir.kt @@ -7,7 +7,7 @@ fun foo(arg: Int?) { } val y: Any? = arg if (y != null) { - arg.hashCode() + arg.hashCode() } val yy: Any? yy = arg diff --git a/compiler/testData/diagnostics/tests/smartCasts/toInvisible.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/toInvisible.fir.kt new file mode 100644 index 00000000000..01e451abd0f --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/toInvisible.fir.kt @@ -0,0 +1,44 @@ +// SKIP_TXT +// FILE: a/A.java +package a; +public interface A { + B b(); +} + +// FILE: a/B.java +package a; +public interface B { + void bar(); +} + +// FILE: a/AImpl.java +package a; + +public class AImpl implements A { + @Override + public BImpl b() { + return new BImpl(); + } +} + +class BImpl implements B { + @Override + public void bar() {} +} + +// FILE: main.kt +import a.A +import a.AImpl + +fun test1(a: A) { + if (a is AImpl) { + (a as A).b().bar() // OK + a.b().bar() + } +} + +fun test2(aImpl: AImpl) { + val a: A = aImpl + (a as A).b().bar() // OK + a.b().bar() // Works at FE1.0, fails at FIR +} diff --git a/compiler/testData/diagnostics/tests/smartCasts/toInvisible.kt b/compiler/testData/diagnostics/tests/smartCasts/toInvisible.kt new file mode 100644 index 00000000000..a0180418aa0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/toInvisible.kt @@ -0,0 +1,45 @@ +// SKIP_TXT +// FILE: a/A.java +package a; +public interface A { + B b(); +} + +// FILE: a/B.java +package a; +public interface B { + void bar(); +} + +// FILE: a/AImpl.java +package a; + +public class AImpl implements A { + @Override + public BImpl b() { + return new BImpl(); + } +} + +class BImpl implements B { + @Override + public void bar() {} +} + +// FILE: main.kt +import a.A +import a.AImpl + +fun test1(a: A) { + if (a is AImpl) { + (a as A).b().bar() // OK + a.b().bar() + } +} + +fun test2(aImpl: AImpl) { + val a: A = aImpl + (a as A).b().bar() // OK + a.b().bar() // Works at FE1.0, fails at FIR +} + diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/whileWithBreak.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/variables/whileWithBreak.fir.kt index 55663623f71..05f04ba2fba 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/whileWithBreak.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/whileWithBreak.fir.kt @@ -4,7 +4,7 @@ fun String.next(): String { fun list(start: String) { var e: Any? = start - if (e==null) return + if (e==null) return while (e is String) { // Smart cast due to the loop condition if (e.length == 0) diff --git a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/boundInitializer.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/boundInitializer.fir.kt index 60589b26bb1..198a64f4326 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/boundInitializer.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/boundInitializer.fir.kt @@ -5,7 +5,7 @@ fun foo(arg: Int?) { } val y: Any? = arg if (y != null) { - arg.hashCode() + arg.hashCode() } val yy: Any? yy = arg diff --git a/compiler/testData/ir/irText/expressions/whenSmartCastToEnum.fir.ir.txt b/compiler/testData/ir/irText/expressions/whenSmartCastToEnum.fir.ir.txt index eab03b1b7aa..564d3b985ce 100644 --- a/compiler/testData/ir/irText/expressions/whenSmartCastToEnum.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/whenSmartCastToEnum.fir.ir.txt @@ -67,8 +67,7 @@ FILE fqName: fileName:/whenSmartCastToEnum.kt WHEN type=kotlin.Unit origin=IF BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.En - TYPE_OP type=.En origin=IMPLICIT_CAST typeOperand=.En - GET_VAR 'val x: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null + GET_VAR 'val x: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null then: BLOCK type=kotlin.Unit origin=WHEN VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.En [val] TYPE_OP type=.En origin=IMPLICIT_CAST typeOperand=.En @@ -99,8 +98,7 @@ FILE fqName: fileName:/whenSmartCastToEnum.kt WHEN type=kotlin.Unit origin=IF BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.En - TYPE_OP type=.En origin=IMPLICIT_CAST typeOperand=.En - GET_VAR 'val y: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + GET_VAR 'val y: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null then: BLOCK type=kotlin.Unit origin=WHEN VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:.En [val] TYPE_OP type=.En origin=IMPLICIT_CAST typeOperand=.En diff --git a/compiler/testData/ir/irText/expressions/whenSmartCastToEnum.fir.kt.txt b/compiler/testData/ir/irText/expressions/whenSmartCastToEnum.fir.kt.txt index 1b37d6124cf..59f4d4f0d28 100644 --- a/compiler/testData/ir/irText/expressions/whenSmartCastToEnum.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/whenSmartCastToEnum.fir.kt.txt @@ -21,7 +21,7 @@ fun test() { var r: String = "" val x: Any? = En.A when { - x /*as En */ is En -> { // BLOCK + x is En -> { // BLOCK val tmp0_subject: En = x /*as En */ when { EQEQ(arg0 = tmp0_subject, arg1 = En.A) -> { // BLOCK @@ -37,7 +37,7 @@ fun test() { } val y: Any = En.A when { - y /*as En */ is En -> { // BLOCK + y is En -> { // BLOCK val tmp1_subject: En = y /*as En */ when { EQEQ(arg0 = tmp1_subject, arg1 = En.A) -> { // BLOCK diff --git a/compiler/testData/ir/irText/firProblems/JCTree.fir.ir.txt b/compiler/testData/ir/irText/firProblems/JCTree.fir.ir.txt index c801cbbe1fc..7c82ebc14ed 100644 --- a/compiler/testData/ir/irText/firProblems/JCTree.fir.ir.txt +++ b/compiler/testData/ir/irText/firProblems/JCTree.fir.ir.txt @@ -29,14 +29,12 @@ FILE fqName: fileName:/JCTreeUser.kt WHEN type=kotlin.Unit origin=IF BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.JCTree.JCTypeApply - TYPE_OP type=T of .Owner origin=IMPLICIT_CAST typeOperand=T of .Owner - GET_VAR 'var tree: .JCTree [var] declared in .Owner.' type=.JCTree origin=null + GET_VAR 'var tree: .JCTree [var] declared in .Owner.' type=.JCTree origin=null then: RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in .Owner' TYPE_OP type=@[FlexibleNullability] kotlin.String origin=IMPLICIT_NOTNULL typeOperand=@[FlexibleNullability] kotlin.String GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:clazz type:@[FlexibleNullability] kotlin.String? visibility:public' type=@[FlexibleNullability] kotlin.String? origin=GET_PROPERTY receiver: TYPE_OP type=.JCTree.JCTypeApply origin=IMPLICIT_CAST typeOperand=.JCTree.JCTypeApply - TYPE_OP type=T of .Owner origin=IMPLICIT_CAST typeOperand=T of .Owner - GET_VAR 'var tree: .JCTree [var] declared in .Owner.' type=.JCTree origin=null + GET_VAR 'var tree: .JCTree [var] declared in .Owner.' type=.JCTree origin=null RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in .Owner' CONST String type=kotlin.String value="" FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] diff --git a/compiler/testData/ir/irText/firProblems/JCTree.fir.kt.txt b/compiler/testData/ir/irText/firProblems/JCTree.fir.kt.txt index 1c83ead98e0..d0640c6e42f 100644 --- a/compiler/testData/ir/irText/firProblems/JCTree.fir.kt.txt +++ b/compiler/testData/ir/irText/firProblems/JCTree.fir.kt.txt @@ -13,7 +13,7 @@ class Owner { get(): String { var tree: JCTree = .() when { - tree /*as T */ is JCTypeApply -> return tree /*as T */ /*as JCTypeApply */.#clazz /*!! @FlexibleNullability String */ + tree is JCTypeApply -> return tree /*as JCTypeApply */.#clazz /*!! @FlexibleNullability String */ } return "" } 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 541c3bb2865..f1a052d046a 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 @@ -27585,6 +27585,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/smartCasts/throwInTry.kt"); } + @Test + @TestMetadata("toInvisible.kt") + public void testToInvisible() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/toInvisible.kt"); + } + @Test @TestMetadata("twoImplicitReceivers.kt") public void testTwoImplicitReceivers() throws Exception { diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/58.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/58.fir.kt index fa31392cd1f..7e3f6a152fe 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/58.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/58.fir.kt @@ -13,7 +13,7 @@ fun case_1() { y = x y.put(0) val z: In<*> = x - z.put(0) + z.put(0) } /* @@ -27,7 +27,7 @@ fun case_2() { y = x y.put(0) val z: Inv = x - z.put(0) + z.put(0) } // TESTCASE NUMBER: 3 @@ -61,7 +61,7 @@ fun case_5() { y = x y.put(0) val z: Inv = x - z.put(0) + z.put(0) } /* @@ -76,5 +76,5 @@ fun case_6() { y = x y.put(0) val z: Inv = x - z.put(0) + z.put(0) }