From d7ee168dffb68dedc3dad653fbf0b11bad704904 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 11 Jun 2020 15:17:21 +0300 Subject: [PATCH] [FIR] Create error candidate for completion instead of simple error reference --- .../resolve/callResolution/errorCandidates.kt | 19 ++ .../callResolution/errorCandidates.txt | 18 ++ .../resolve/cfg/flowFromInplaceLambda.dot | 196 +++++++++--------- .../CallBasedInExpressionGenerator.txt | 2 +- .../inference/typeParameters2.txt | 2 +- .../resolve/lambdaArgInScopeFunction.txt | 4 +- .../resolve/lambdaPropertyTypeInference.txt | 8 +- .../resolve/samConversions/kotlinSam.txt | 4 +- .../notSamBecauseOfSupertype.txt | 2 +- .../testData/resolve/sealedClass.txt | 2 +- .../callableReferences/implicitTypes.txt | 2 +- .../delegates/delegateWithAnonymousObject.dot | 24 +-- .../delegates/simpleDelegatedToMap.txt | 12 +- .../fir/FirDiagnosticsTestGenerated.java | 5 + ...DiagnosticsWithLightTreeTestGenerated.java | 5 + .../jetbrains/kotlin/fir/FirCallResolver.kt | 65 ++++-- .../kotlin/fir/resolve/calls/Arguments.kt | 26 +-- .../fir/resolve/calls/CandidateFactory.kt | 54 +++++ .../kotlin/fir/resolve/calls/CheckerSink.kt | 8 +- .../calls/FirNamedReferenceWithCandidate.kt | 14 +- .../resolve/calls/ResolutionStageRunner.kt | 4 +- .../kotlin/fir/resolve/calls/ResolverParts.kt | 3 +- .../fir/resolve/inference/FirCallCompleter.kt | 20 +- .../fir/resolve/inference/InferenceUtils.kt | 8 +- .../resolve/inference/PostponedArguments.kt | 6 +- ...rCallCompletionResultsWriterTransformer.kt | 63 +++--- .../FirExpressionsResolveTransformer.kt | 7 +- .../recursiveLocalFuns/selfCall.fir.kt | 2 +- .../tests/regressions/kt10843.fir.kt | 2 +- .../adaptedExtensionFunctions.fir.txt | 2 +- .../boundInlineAdaptedReference.fir.txt | 2 +- .../suspendConversion.fir.txt | 2 +- .../typeParametersInImplicitCast.fir.txt | 10 +- .../diagnostics/notLinked/dfa/neg/31.fir.kt | 2 +- .../diagnostics/notLinked/dfa/neg/32.fir.kt | 6 +- .../diagnostics/notLinked/dfa/pos/2.fir.kt | 2 +- .../org/jetbrains/kotlin/utils/addToStdlib.kt | 4 +- 37 files changed, 369 insertions(+), 248 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt b/compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt new file mode 100644 index 00000000000..6989a80856a --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt @@ -0,0 +1,19 @@ +fun foo(x: Int) {} + +interface A +interface B +interface C : A, B + +fun bar(x: A) {} +fun bar(x: B) {} + +fun test(c: C) { + // Argument mapping error + foo("") + + // Ambiguity + bar(c) + + // Unresolved reference + baz() +} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.txt b/compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.txt new file mode 100644 index 00000000000..ca68824e1ad --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.txt @@ -0,0 +1,18 @@ +FILE: errorCandidates.kt + public final fun foo(x: R|kotlin/Int|): R|kotlin/Unit| { + } + public abstract interface A : R|kotlin/Any| { + } + public abstract interface B : R|kotlin/Any| { + } + public abstract interface C : R|A|, R|B| { + } + public final fun bar(x: R|A|): R|kotlin/Unit| { + } + public final fun bar(x: R|B|): R|kotlin/Unit| { + } + public final fun test(c: R|C|): R|kotlin/Unit| { + #(String()) + #(R|/c|) + #() + } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot index dcc0022e39c..3df2428ebc2 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/flowFromInplaceLambda.dot @@ -272,12 +272,12 @@ digraph flowFromInplaceLambda_kt { 107 [label="Postponed enter to lambda"]; subgraph cluster_14 { color=blue - 126 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - 128 [label="Access variable R|/y|"]; - 129 [label="Function call: R|/y|.#()"]; - 130 [label="Access variable R|/x|"]; - 131 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; - 127 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 124 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 126 [label="Access variable R|/y|"]; + 127 [label="Function call: R|/y|.#()"]; + 128 [label="Access variable R|/x|"]; + 129 [label="Type operator: (R|/x| as R|kotlin/Int|)"]; + 125 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 108 [label="Postponed exit from lambda"]; 109 [label="Function call: R|/myRun|(...)"]; @@ -287,38 +287,36 @@ digraph flowFromInplaceLambda_kt { 113 [label="Postponed enter to lambda"]; subgraph cluster_15 { color=blue - 132 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - 134 [label="Access variable R|/x|"]; - 135 [label="Function call: R|/x|.#()"]; - 136 [label="Access variable R|/y|"]; - 137 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; - 138 [label="Const: Int(1)"]; - 133 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 130 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 132 [label="Access variable R|/x|"]; + 133 [label="Function call: R|/x|.#()"]; + 134 [label="Access variable R|/y|"]; + 135 [label="Function call: R|/y|.R|kotlin/Int.inc|()"]; + 136 [label="Const: Int(1)"]; + 131 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } 114 [label="Postponed exit from lambda"]; 115 [label="Function call: R|/myRun|(...)"]; 116 [label="Function call: R|/select|(...)"]; 117 [label="Variable declaration: lval a: R|kotlin/Int|"]; 118 [label="Access variable R|/x|"]; - 119 [label="Access variable R|/x|"]; - 120 [label="Access variable R|/x|"]; - 121 [label="Function call: #(...)"]; - 122 [label="Access variable R|/y|"]; + 119 [label="Function call: #(...)"]; + 120 [label="Access variable R|/y|"]; + 121 [label="Function call: R|/takeInt|(...)"]; + 122 [label="Access variable R|/a|"]; 123 [label="Function call: R|/takeInt|(...)"]; - 124 [label="Access variable R|/a|"]; - 125 [label="Function call: R|/takeInt|(...)"]; 106 [label="Exit function test_4" style="filled" fillcolor=red]; } 105 -> {107}; 107 -> {108}; - 107 -> {126} [color=red]; + 107 -> {124} [color=red]; 108 -> {109}; 109 -> {110}; 110 -> {111}; 111 -> {112}; 112 -> {113}; 113 -> {114}; - 113 -> {132} [color=red]; + 113 -> {130} [color=red]; 114 -> {115}; 115 -> {116}; 116 -> {117}; @@ -328,110 +326,108 @@ digraph flowFromInplaceLambda_kt { 120 -> {121}; 121 -> {122}; 122 -> {123}; - 123 -> {124}; - 124 -> {125}; - 125 -> {106}; - 126 -> {128}; + 123 -> {106}; + 124 -> {126}; + 126 -> {127}; + 127 -> {128}; 128 -> {129}; - 129 -> {130}; - 130 -> {131}; - 131 -> {127}; - 132 -> {134}; + 129 -> {125}; + 130 -> {132}; + 132 -> {133}; + 133 -> {134}; 134 -> {135}; 135 -> {136}; - 136 -> {137}; - 137 -> {138}; - 138 -> {133}; + 136 -> {131}; subgraph cluster_16 { color=red - 139 [label="Enter function test_5" style="filled" fillcolor=red]; - 141 [label="Postponed enter to lambda"]; + 137 [label="Enter function test_5" style="filled" fillcolor=red]; + 139 [label="Postponed enter to lambda"]; subgraph cluster_17 { color=blue - 152 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - 154 [label="Function call: R|/materialize|()"]; - 153 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 150 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 152 [label="Function call: R|/materialize|()"]; + 151 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 142 [label="Postponed exit from lambda"]; - 143 [label="Function call: R|kotlin/run|(...)"]; - 144 [label="Postponed enter to lambda"]; + 140 [label="Postponed exit from lambda"]; + 141 [label="Function call: R|kotlin/run|(...)"]; + 142 [label="Postponed enter to lambda"]; subgraph cluster_18 { color=blue - 155 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - 157 [label="Function call: R|/materialize|()"]; - 156 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 153 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 155 [label="Function call: R|/materialize|()"]; + 154 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 145 [label="Postponed exit from lambda"]; - 146 [label="Function call: R|kotlin/run|(...)"]; - 148 [label="Call arguments union" style="filled" fillcolor=yellow]; - 147 [label="Function call: R|/select|(...)"]; - 149 [label="Variable declaration: lval x: R|kotlin/Int|"]; - 150 [label="Access variable R|/x|"]; - 151 [label="Function call: R|/takeInt|(...)"]; - 140 [label="Exit function test_5" style="filled" fillcolor=red]; + 143 [label="Postponed exit from lambda"]; + 144 [label="Function call: R|kotlin/run|(...)"]; + 146 [label="Call arguments union" style="filled" fillcolor=yellow]; + 145 [label="Function call: R|/select|(...)"]; + 147 [label="Variable declaration: lval x: R|kotlin/Int|"]; + 148 [label="Access variable R|/x|"]; + 149 [label="Function call: R|/takeInt|(...)"]; + 138 [label="Exit function test_5" style="filled" fillcolor=red]; } - 139 -> {141}; - 141 -> {152}; - 141 -> {142} [color=red]; - 142 -> {143}; + 137 -> {139}; + 139 -> {150}; + 139 -> {140} [color=red]; + 140 -> {141}; + 141 -> {142}; + 142 -> {153}; + 142 -> {143} [color=red]; 143 -> {144}; - 144 -> {155}; - 144 -> {145} [color=red]; - 145 -> {146}; - 146 -> {148}; - 147 -> {149}; - 148 -> {147}; - 149 -> {150}; - 150 -> {151}; - 151 -> {140}; - 152 -> {154}; - 153 -> {142} [color=green]; - 153 -> {148} [color=red]; - 154 -> {153}; - 155 -> {157}; - 156 -> {145} [color=green]; - 156 -> {148} [color=red]; - 157 -> {156}; + 144 -> {146}; + 145 -> {147}; + 146 -> {145}; + 147 -> {148}; + 148 -> {149}; + 149 -> {138}; + 150 -> {152}; + 151 -> {140} [color=green]; + 151 -> {146} [color=red]; + 152 -> {151}; + 153 -> {155}; + 154 -> {143} [color=green]; + 154 -> {146} [color=red]; + 155 -> {154}; subgraph cluster_19 { color=red - 158 [label="Enter function test_6" style="filled" fillcolor=red]; - 160 [label="Postponed enter to lambda"]; + 156 [label="Enter function test_6" style="filled" fillcolor=red]; + 158 [label="Postponed enter to lambda"]; subgraph cluster_20 { color=blue - 165 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - 167 [label="Postponed enter to lambda"]; + 163 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 165 [label="Postponed enter to lambda"]; subgraph cluster_21 { color=blue - 170 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; - 172 [label="Function call: R|/materialize|()"]; - 171 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 168 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; + 170 [label="Function call: R|/materialize|()"]; + 169 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 168 [label="Postponed exit from lambda"]; - 169 [label="Function call: R|kotlin/run|(...)"]; - 166 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; + 166 [label="Postponed exit from lambda"]; + 167 [label="Function call: R|kotlin/run|(...)"]; + 164 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 161 [label="Postponed exit from lambda"]; - 162 [label="Function call: R|/myRun|(...)"]; - 163 [label="Function call: R|/id|(...)"]; - 164 [label="Variable declaration: lval x: R|kotlin/String|"]; - 159 [label="Exit function test_6" style="filled" fillcolor=red]; + 159 [label="Postponed exit from lambda"]; + 160 [label="Function call: R|/myRun|(...)"]; + 161 [label="Function call: R|/id|(...)"]; + 162 [label="Variable declaration: lval x: R|kotlin/String|"]; + 157 [label="Exit function test_6" style="filled" fillcolor=red]; } - 158 -> {160}; + 156 -> {158}; + 158 -> {159}; + 158 -> {163} [color=red]; + 159 -> {160}; 160 -> {161}; - 160 -> {165} [color=red]; 161 -> {162}; - 162 -> {163}; - 163 -> {164}; - 164 -> {159}; - 165 -> {167}; - 167 -> {170}; - 167 -> {168} [color=red]; - 168 -> {169}; - 169 -> {166}; - 170 -> {172}; - 171 -> {168} [color=green]; - 172 -> {171}; + 162 -> {157}; + 163 -> {165}; + 165 -> {168}; + 165 -> {166} [color=red]; + 166 -> {167}; + 167 -> {164}; + 168 -> {170}; + 169 -> {166} [color=green]; + 170 -> {169}; } diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/CallBasedInExpressionGenerator.txt b/compiler/fir/analysis-tests/testData/resolve/expresssions/CallBasedInExpressionGenerator.txt index 60a813d799c..71faa0653ab 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/CallBasedInExpressionGenerator.txt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/CallBasedInExpressionGenerator.txt @@ -14,7 +14,7 @@ FILE: CallBasedInExpressionGenerator.kt private get(): R|kotlin/Boolean| public final override fun generate(argument: R|ERROR CLASS: Symbol not found, for `StackValue`|): R|ERROR CLASS: Symbol not found, for `BranchedValue`| { - ^generate R?C|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.gen|(R|/argument|).#( = let@fun (): R|ERROR CLASS: Can't resolve when expression| { + ^generate this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.gen|(R|/argument|).#( = let@fun (): { ^ when () { this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.isInverted| -> { #(#) diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/inference/typeParameters2.txt b/compiler/fir/analysis-tests/testData/resolve/expresssions/inference/typeParameters2.txt index db7289b97f7..c3db7c75f76 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/inference/typeParameters2.txt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/inference/typeParameters2.txt @@ -17,6 +17,6 @@ FILE: typeParameters2.kt ^foo R|/t| } public final fun main(fooImpl: R|FooImpl|, fooBarImpl: R|FooBarImpl|): R|kotlin/Unit| { - lval a: = #(R|/fooBarImpl|) + lval a: = #(R|/fooBarImpl|) lval b: R|Foo| = R|/foo|(R|/fooImpl|) } diff --git a/compiler/fir/analysis-tests/testData/resolve/lambdaArgInScopeFunction.txt b/compiler/fir/analysis-tests/testData/resolve/lambdaArgInScopeFunction.txt index 21647b88521..2fd08db01c9 100644 --- a/compiler/fir/analysis-tests/testData/resolve/lambdaArgInScopeFunction.txt +++ b/compiler/fir/analysis-tests/testData/resolve/lambdaArgInScopeFunction.txt @@ -29,7 +29,7 @@ FILE: lambdaArgInScopeFunction.kt } ) } R|/lambda|.R|tests/_checkType/checkType| KotlinClass|>( = checkType@fun R|tests/_checkType/Inv?>|.(): R|kotlin/Unit| { - ^ # KotlinClass?|>() + ^ #() } ) } @@ -50,7 +50,7 @@ FILE: lambdaArgInScopeFunction.kt } ) R|/lambda|.R|tests/_checkType/checkType| KotlinClass|>( = checkType@fun R|tests/_checkType/Inv>|.(): R|kotlin/Unit| { - ^ # KotlinClass?|>() + ^ #() } ) } diff --git a/compiler/fir/analysis-tests/testData/resolve/lambdaPropertyTypeInference.txt b/compiler/fir/analysis-tests/testData/resolve/lambdaPropertyTypeInference.txt index 212a422d05b..135b23a5b72 100644 --- a/compiler/fir/analysis-tests/testData/resolve/lambdaPropertyTypeInference.txt +++ b/compiler/fir/analysis-tests/testData/resolve/lambdaPropertyTypeInference.txt @@ -29,11 +29,11 @@ FILE: KotlinClass.kt } ) R|/invalidType|.R|tests/_checkType/checkType| kotlin/Boolean|>( = checkType@fun R|tests/_checkType/Inv>|.(): R|kotlin/Unit| { - ^ # kotlin/Boolean|>() + ^ #() } ) R|/Case1.Case1|(R|/javaClass|).R|/Case1.x|.R|tests/_checkType/checkType| kotlin/Boolean|>( = checkType@fun R|tests/_checkType/Inv>|.(): R|kotlin/Unit| { - ^ # kotlin/Boolean|>() + ^ #() } ) } @@ -122,11 +122,11 @@ FILE: KotlinClass.kt } ) R|/invalidType|.R|tests/_checkType/checkType| kotlin/Boolean|>( = checkType@fun R|tests/_checkType/Inv>|.(): R|kotlin/Unit| { - ^ # kotlin/Boolean|>() + ^ #() } ) R|/Case2.Case2|(R|/kotlinClass|).R|/Case2.x|.R|tests/_checkType/checkType| kotlin/Boolean|>( = checkType@fun R|tests/_checkType/Inv>|.(): R|kotlin/Unit| { - ^ # kotlin/Boolean|>() + ^ #() } ) } diff --git a/compiler/fir/analysis-tests/testData/resolve/samConversions/kotlinSam.txt b/compiler/fir/analysis-tests/testData/resolve/samConversions/kotlinSam.txt index a2a4cdd056e..c9d524a906d 100644 --- a/compiler/fir/analysis-tests/testData/resolve/samConversions/kotlinSam.txt +++ b/compiler/fir/analysis-tests/testData/resolve/samConversions/kotlinSam.txt @@ -38,12 +38,12 @@ FILE: kotlinSam.kt } ) R|/foo1|(R|/f|) - #( = foo2@fun (x: R|ERROR CLASS: No type for parameter|): R|kotlin/Boolean| { + #( = foo2@fun (x: R|kotlin/Nothing|): R|kotlin/Boolean| { ^ CMP(>, R|/x|.#(Int(1))) } ) #(R|/f|) - #( = foo3@fun (x: R|ERROR CLASS: No type for parameter|): R|kotlin/Boolean| { + #( = foo3@fun (x: R|kotlin/Nothing|): R|kotlin/Boolean| { ^ CMP(>, R|/x|.#(Int(1))) } ) diff --git a/compiler/fir/analysis-tests/testData/resolve/samConversions/notSamBecauseOfSupertype.txt b/compiler/fir/analysis-tests/testData/resolve/samConversions/notSamBecauseOfSupertype.txt index e5a92e09593..b9ffbb30e9b 100644 --- a/compiler/fir/analysis-tests/testData/resolve/samConversions/notSamBecauseOfSupertype.txt +++ b/compiler/fir/analysis-tests/testData/resolve/samConversions/notSamBecauseOfSupertype.txt @@ -2,7 +2,7 @@ FILE: main.kt public final fun foo(m: R|MyRunnable|): R|kotlin/Unit| { } public final fun main(): R|kotlin/Unit| { - Q|JavaUsage|.#( = foo@fun (x: R|ERROR CLASS: No type for parameter|): R|kotlin/Boolean| { + Q|JavaUsage|.#( = foo@fun (x: R|kotlin/Nothing|): R|kotlin/Boolean| { ^ CMP(>, R|/x|.#(Int(1))) } ) diff --git a/compiler/fir/analysis-tests/testData/resolve/sealedClass.txt b/compiler/fir/analysis-tests/testData/resolve/sealedClass.txt index 746394bc5ee..0f0589d2813 100644 --- a/compiler/fir/analysis-tests/testData/resolve/sealedClass.txt +++ b/compiler/fir/analysis-tests/testData/resolve/sealedClass.txt @@ -35,7 +35,7 @@ FILE: sealedClass.kt } public final object Second : R|WithPrivateConstructor| { private constructor(): R|Second| { - super(IntegerLiteral(0)) + super(Int(0)) } } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/callableReferences/implicitTypes.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/callableReferences/implicitTypes.txt index 8cfa49e1956..b85e9e78b55 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/callableReferences/implicitTypes.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/callableReferences/implicitTypes.txt @@ -12,5 +12,5 @@ FILE: implicitTypes.kt ^loop1 #(::R|/loop2|) } public final fun loop2(): { - ^loop2 R?C|/loop1|() + ^loop2 R|/loop1|() } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/delegateWithAnonymousObject.dot b/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/delegateWithAnonymousObject.dot index 79d5c503af9..911cb02ce84 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/delegateWithAnonymousObject.dot +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/delegateWithAnonymousObject.dot @@ -117,7 +117,7 @@ digraph delegateWithAnonymousObject_kt { subgraph cluster_11 { color=red - 66 [label="Enter class IssuesListUserProfile" style="filled" fillcolor=red]; + 64 [label="Enter class IssuesListUserProfile" style="filled" fillcolor=red]; subgraph cluster_12 { color=blue 48 [label="Enter function setter" style="filled" fillcolor=red]; @@ -144,36 +144,32 @@ digraph delegateWithAnonymousObject_kt { 57 [label="Postponed exit from lambda"]; 58 [label="Function call: this@R|/IssuesListUserProfile|.R|/delegate|(...)"]; 59 [label="Access variable this@R|/IssuesListUserProfile|"]; - 60 [label="Access variable this@R|/IssuesListUserProfile|"]; - 61 [label="Access variable this@R|/IssuesListUserProfile|"]; - 62 [label="Function call: this@R|/IssuesListUserProfile|.R|/delegate|(...).#(...)"]; - 63 [label="Postponed enter to lambda"]; + 60 [label="Function call: this@R|/IssuesListUserProfile|.R|/delegate|(...).#(...)"]; + 61 [label="Postponed enter to lambda"]; subgraph cluster_15 { color=blue 21 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; 23 [label="Exit anonymous object"]; 22 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; } - 64 [label="Postponed exit from lambda"]; - 65 [label="Function call: this@R|/IssuesListUserProfile|.R|/delegate|(...)"]; + 62 [label="Postponed exit from lambda"]; + 63 [label="Function call: this@R|/IssuesListUserProfile|.R|/delegate|(...)"]; 55 [label="Exit property" style="filled" fillcolor=red]; } - 67 [label="Exit class IssuesListUserProfile" style="filled" fillcolor=red]; + 65 [label="Exit class IssuesListUserProfile" style="filled" fillcolor=red]; } - 66 -> {54} [color=green]; + 64 -> {54} [color=green]; 54 -> {56}; - 55 -> {67} [color=green]; + 55 -> {65} [color=green]; 56 -> {57}; 57 -> {58}; 58 -> {59}; 59 -> {60}; 60 -> {61}; 61 -> {62}; + 61 -> {21} [color=red]; 62 -> {63}; - 63 -> {64}; - 63 -> {21} [color=red]; - 64 -> {65}; - 65 -> {55}; + 63 -> {55}; 21 -> {23}; 21 -> {24 27 32} [color=red]; 23 -> {22}; diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/simpleDelegatedToMap.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/simpleDelegatedToMap.txt index a99b5c2abfb..51c37cff0e6 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/simpleDelegatedToMap.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/delegates/simpleDelegatedToMap.txt @@ -7,19 +7,19 @@ FILE: simpleDelegatedToMap.kt public final val map: R|kotlin/collections/MutableMap| = R|/map| public get(): R|kotlin/collections/MutableMap| - public final var foo: by R|/map| - public get(): { + public final var foo: R|ERROR CLASS: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]|by R|/map| + public get(): R|ERROR CLASS: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]| { ^ this@R|/C|.D|/C.foo|.#(this@R|/C|, ::R|/C.foo|) } - public set(: ): R|kotlin/Unit| { + public set(: R|ERROR CLASS: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]|): R|kotlin/Unit| { this@R|/C|.D|/C.foo|.#(this@R|/C|, ::R|/C.foo|, R|/foo|) } } - public final var bar: by R|kotlin/collections/hashMapOf|() - public get(): { + public final var bar: R|ERROR CLASS: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]|by R|kotlin/collections/hashMapOf|() + public get(): R|ERROR CLASS: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]| { ^ D|/bar|.#(Null(null), ::R|/bar|) } - public set(: ): R|kotlin/Unit| { + public set(: R|ERROR CLASS: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]|): R|kotlin/Unit| { D|/bar|.#(Null(null), ::R|/bar|, R|/bar|) } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 8cae7a39dd8..35aef32ec2d 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -614,6 +614,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.kt"); } + @TestMetadata("errorCandidates.kt") + public void testErrorCandidates() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt"); + } + @TestMetadata("extensionInvokeAfterSafeCall.kt") public void testExtensionInvokeAfterSafeCall() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/extensionInvokeAfterSafeCall.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 369f1baa2b7..46b25e9cf9a 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -614,6 +614,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/debugInfoCall.kt"); } + @TestMetadata("errorCandidates.kt") + public void testErrorCandidates() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/errorCandidates.kt"); + } + @TestMetadata("extensionInvokeAfterSafeCall.kt") public void testExtensionInvokeAfterSafeCall() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/extensionInvokeAfterSafeCall.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index 5b223356189..9d2efc0117a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.declarations.isInner +import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedReifiedParameterReference @@ -73,13 +74,14 @@ class FirCallResolver( val nameReference = createResolvedNamedReference( functionCall.calleeReference, name, + result.info, result.candidates, result.applicability, functionCall.explicitReceiver, ) val resultExpression = functionCall.transformCalleeReference(StoreNameReference, nameReference) - val candidate = resultExpression.candidate() + val candidate = (nameReference as? FirNamedReferenceWithCandidate)?.candidate // We need desugaring val resultFunctionCall = if (candidate != null && candidate.callInfo != result.info) { @@ -162,6 +164,7 @@ class FirCallResolver( val nameReference = createResolvedNamedReference( callee, callee.name, + result.info, reducedCandidates, result.applicability, qualifiedAccess.explicitReceiver, @@ -284,11 +287,11 @@ class FirCallResolver( constructorClassSymbol, ) - return callResolver.selectDelegatingConstructorCall(delegatedConstructorCall, name, result) + return callResolver.selectDelegatingConstructorCall(delegatedConstructorCall, name, result, callInfo) } private fun selectDelegatingConstructorCall( - call: FirDelegatedConstructorCall, name: Name, result: CandidateCollector, + call: FirDelegatedConstructorCall, name: Name, result: CandidateCollector, callInfo: CallInfo ): FirDelegatedConstructorCall { val bestCandidates = result.bestCandidates() val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) { @@ -300,6 +303,7 @@ class FirCallResolver( val nameReference = createResolvedNamedReference( call.calleeReference, name, + callInfo, reducedCandidates, result.currentApplicability, ) @@ -348,29 +352,31 @@ class FirCallResolver( private fun createResolvedNamedReference( reference: FirReference, name: Name, + callInfo: CallInfo, candidates: Collection, applicability: CandidateApplicability, explicitReceiver: FirExpression? = null, ): FirNamedReference { val source = reference.source return when { - candidates.isEmpty() -> buildErrorNamedReference { - this.source = source - diagnostic = ConeUnresolvedNameError(name) - } + candidates.isEmpty() -> buildErrorReference( + callInfo, + ConeUnresolvedNameError(name), + source, + name + ) applicability < CandidateApplicability.SYNTHETIC_RESOLVED -> { - buildErrorNamedReference { - this.source = source - diagnostic = ConeInapplicableCandidateError( - applicability, - candidates.map { - ConeInapplicableCandidateError.CandidateInfo( - it.symbol, - if (it.systemInitialized) it.system.diagnostics else emptyList(), - ) - }, - ) - } + val diagnostic = ConeInapplicableCandidateError( + applicability, + candidates.map { + ConeInapplicableCandidateError.CandidateInfo( + it.symbol, + if (it.systemInitialized) it.system.diagnostics else emptyList(), + ) + } + ) + + buildErrorReference(callInfo, diagnostic, source, name) } candidates.size == 1 -> { val candidate = candidates.single() @@ -396,10 +402,23 @@ class FirCallResolver( } FirNamedReferenceWithCandidate(source, name, candidate) } - else -> buildErrorNamedReference { - this.source = source - diagnostic = ConeAmbiguityError(name, candidates.map { it.symbol }) - } + else -> buildErrorReference( + callInfo, + ConeAmbiguityError(name, candidates.map { it.symbol }), + source, + name + ) } } + + private fun buildErrorReference( + callInfo: CallInfo, + diagnostic: ConeDiagnostic, + source: FirSourceElement?, + name: Name + ): FirErrorReferenceWithCandidate { + val candidate = CandidateFactory(components, callInfo).createErrorCandidate(diagnostic) + resolutionStageRunner.processCandidate(candidate, stopOnFirstError = false) + return FirErrorReferenceWithCandidate(source, name, candidate, diagnostic) + } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index 387eb14b1a9..8be2624cbdf 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -35,8 +35,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs fun Candidate.resolveArgumentExpression( csBuilder: ConstraintSystemBuilder, argument: FirExpression, - expectedType: ConeKotlinType, - expectedTypeRef: FirTypeRef, + expectedType: ConeKotlinType?, + expectedTypeRef: FirTypeRef?, sink: CheckerSink, isReceiver: Boolean, isDispatch: Boolean @@ -73,7 +73,7 @@ fun Candidate.resolveArgumentExpression( checkApplicabilityForArgumentType( csBuilder, StandardClassIds.Unit.constructClassLikeType(emptyArray(), isNullable = false), - expectedType.type, + expectedType?.type, SimpleConstraintSystemConstraintPosition, isReceiver = false, isDispatch = false, @@ -122,8 +122,8 @@ fun Candidate.resolveArgumentExpression( private fun Candidate.resolveBlockArgument( csBuilder: ConstraintSystemBuilder, block: FirBlock, - expectedType: ConeKotlinType, - expectedTypeRef: FirTypeRef, + expectedType: ConeKotlinType?, + expectedTypeRef: FirTypeRef?, sink: CheckerSink, isReceiver: Boolean, isDispatch: Boolean @@ -133,7 +133,7 @@ private fun Candidate.resolveBlockArgument( checkApplicabilityForArgumentType( csBuilder, block.typeRef.coneTypeUnsafe(), - expectedType.type, + expectedType?.type, SimpleConstraintSystemConstraintPosition, isReceiver = false, isDispatch = false, @@ -157,7 +157,7 @@ private fun Candidate.resolveBlockArgument( fun Candidate.resolveSubCallArgument( csBuilder: ConstraintSystemBuilder, argument: FirResolvable, - expectedType: ConeKotlinType, + expectedType: ConeKotlinType?, sink: CheckerSink, isReceiver: Boolean, isDispatch: Boolean, @@ -210,7 +210,7 @@ private fun Candidate.checkApplicabilityForIntegerOperatorCall(sink: CheckerSink fun Candidate.resolvePlainArgumentType( csBuilder: ConstraintSystemBuilder, argumentType: ConeKotlinType, - expectedType: ConeKotlinType, + expectedType: ConeKotlinType?, sink: CheckerSink, isReceiver: Boolean, isDispatch: Boolean, @@ -257,12 +257,13 @@ private fun Candidate.captureTypeFromExpressionOrNull(argumentType: ConeKotlinTy private fun checkApplicabilityForArgumentType( csBuilder: ConstraintSystemBuilder, argumentType: ConeKotlinType, - expectedType: ConeKotlinType, + expectedType: ConeKotlinType?, position: SimpleConstraintSystemConstraintPosition, isReceiver: Boolean, isDispatch: Boolean, sink: CheckerSink ) { + if (expectedType == null) return if (isReceiver && isDispatch) { if (!expectedType.isNullable && argumentType.isMarkedNullable) { sink.reportApplicability(CandidateApplicability.WRONG_RECEIVER) @@ -288,7 +289,7 @@ private fun checkApplicabilityForArgumentType( internal fun Candidate.resolveArgument( argument: FirExpression, - parameter: FirValueParameter, + parameter: FirValueParameter?, isReceiver: Boolean, isSafeCall: Boolean, sink: CheckerSink @@ -299,14 +300,15 @@ internal fun Candidate.resolveArgument( this.system.getBuilder(), argument, expectedType, - parameter.returnTypeRef, + parameter?.returnTypeRef, sink, isReceiver, false ) } -private fun Candidate.prepareExpectedType(session: FirSession, argument: FirExpression, parameter: FirValueParameter): ConeKotlinType { +private fun Candidate.prepareExpectedType(session: FirSession, argument: FirExpression, parameter: FirValueParameter?): ConeKotlinType? { + if (parameter == null) return null if (parameter.returnTypeRef is FirILTTypeRefPlaceHolder) return argument.resultType.coneTypeUnsafe() val basicExpectedType = argument.getExpectedType(session, parameter/*, LanguageVersionSettings*/) val expectedType = getExpectedTypeWithSAMConversion(session, argument, basicExpectedType) ?: basicExpectedType diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt index ac21acb3aea..e541ddd0818 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt @@ -5,10 +5,19 @@ package org.jetbrains.kotlin.fir.resolve.calls +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.declarations.builder.buildErrorFunction +import org.jetbrains.kotlin.fir.declarations.builder.buildErrorProperty +import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.returnExpressions import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirErrorFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirErrorPropertySymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind @@ -55,6 +64,51 @@ class CandidateFactory private constructor( } ?: callInfo ) } + + fun createErrorCandidate(diagnostic: ConeDiagnostic): Candidate { + val symbol: AbstractFirBasedSymbol<*> = when (callInfo.callKind) { + CallKind.VariableAccess -> createErrorPropertySymbol(diagnostic) + CallKind.Function, + CallKind.DelegatingConstructorCall, + CallKind.CallableReference -> createErrorFunctionSymbol(diagnostic) + CallKind.SyntheticSelect -> throw IllegalStateException() + CallKind.SyntheticIdForCallableReferencesResolution -> throw IllegalStateException() + } + return Candidate( + symbol, + dispatchReceiverValue = null, + implicitExtensionReceiverValue = null, + explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, + bodyResolveComponents, + baseSystem, + callInfo + ) + } + + private fun createErrorFunctionSymbol(diagnostic: ConeDiagnostic): FirErrorFunctionSymbol { + return FirErrorFunctionSymbol().also { + buildErrorFunction { + session = this@CandidateFactory.bodyResolveComponents.session + resolvePhase = FirResolvePhase.BODY_RESOLVE + origin = FirDeclarationOrigin.Synthetic + this.diagnostic = diagnostic + symbol = it + } + } + } + + private fun createErrorPropertySymbol(diagnostic: ConeDiagnostic): FirErrorPropertySymbol { + return FirErrorPropertySymbol(diagnostic).also { + buildErrorProperty { + session = this@CandidateFactory.bodyResolveComponents.session + resolvePhase = FirResolvePhase.BODY_RESOLVE + origin = FirDeclarationOrigin.Synthetic + name = FirErrorPropertySymbol.NAME + this.diagnostic = diagnostic + symbol = it + } + } + } } fun PostponedArgumentsAnalyzer.Context.addSubsystemFromExpression(statement: FirStatement) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CheckerSink.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CheckerSink.kt index fc3f2e15e6e..f386417b439 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CheckerSink.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CheckerSink.kt @@ -32,7 +32,11 @@ suspend inline fun CheckerSink.yieldApplicability(new: CandidateApplicability) { yieldIfNeed() } -class CheckerSinkImpl(override val components: InferenceComponents, var continuation: Continuation? = null) : CheckerSink() { +class CheckerSinkImpl( + override val components: InferenceComponents, + var continuation: Continuation? = null, + val stopOnFirstError: Boolean = true +) : CheckerSink() { var current = CandidateApplicability.RESOLVED private set @@ -47,6 +51,6 @@ class CheckerSinkImpl(override val components: InferenceComponents, var continua } override val needYielding: Boolean - get() = current < CandidateApplicability.SYNTHETIC_RESOLVED + get() = stopOnFirstError && current < CandidateApplicability.SYNTHETIC_RESOLVED } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirNamedReferenceWithCandidate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirNamedReferenceWithCandidate.kt index c9f95ab5ab7..14ee41fa03d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirNamedReferenceWithCandidate.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirNamedReferenceWithCandidate.kt @@ -7,16 +7,28 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.name.Name @OptIn(FirImplementationDetail::class) -class FirNamedReferenceWithCandidate( +open class FirNamedReferenceWithCandidate( source: FirSourceElement?, name: Name, val candidate: Candidate ) : FirSimpleNamedReference(source, name, candidate.symbol) { override val candidateSymbol: AbstractFirBasedSymbol<*> get() = candidate.symbol + + open val isError: Boolean get() = false +} + +class FirErrorReferenceWithCandidate( + source: FirSourceElement?, + name: Name, + candidate: Candidate, + val diagnostic: ConeDiagnostic +) : FirNamedReferenceWithCandidate(source, name, candidate) { + override val isError: Boolean get() = true } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStageRunner.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStageRunner.kt index bb86f6ef5fd..964e66636db 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStageRunner.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStageRunner.kt @@ -13,8 +13,8 @@ import kotlin.coroutines.intrinsics.createCoroutineUnintercepted import kotlin.coroutines.resume class ResolutionStageRunner(val components: InferenceComponents) { - fun processCandidate(candidate: Candidate): CandidateApplicability { - val sink = CheckerSinkImpl(components) + fun processCandidate(candidate: Candidate, stopOnFirstError: Boolean = true): CandidateApplicability { + val sink = CheckerSinkImpl(components, stopOnFirstError = stopOnFirstError) var finished = false sink.continuation = suspend { for (stage in candidate.callInfo.callKind.resolutionSequence) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt index 9a3308909d4..9b911720ff8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt @@ -186,7 +186,8 @@ internal object CheckArguments : CheckerStage() { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { val argumentMapping = candidate.argumentMapping ?: throw IllegalStateException("Argument should be already mapped while checking arguments!") - for ((argument, parameter) in argumentMapping) { + for (argument in callInfo.arguments) { + val parameter = argumentMapping[argument] candidate.resolveArgument( argument, parameter, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt index 2e583e058e2..4321d5a139d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.FirResolvable import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.ResolutionMode +import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.calls.candidate import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer @@ -51,24 +52,9 @@ class FirCallCompleter( fun completeCall(call: T, expectedTypeRef: FirTypeRef?): CompletionResult where T : FirResolvable, T : FirStatement { val typeRef = typeFromCallee(call) - if (typeRef.type is ConeKotlinErrorType) { - if (call is FirExpression) { - call.resultType = typeRef - } - val errorCall = if (call is FirFunctionCall) { - call.argumentList.transformArguments( - transformer, - ResolutionMode.WithExpectedType(typeRef.resolvedTypeFromPrototype(session.builtinTypes.nullableAnyType.type)) - ) - call - } else { - call - } - inferenceSession.addErrorCall(errorCall) - return CompletionResult(errorCall, true) - } - val candidate = call.candidate() ?: return CompletionResult(call, true) + val reference = call.calleeReference as? FirNamedReferenceWithCandidate ?: return CompletionResult(call, true) + val candidate = reference.candidate val initialSubstitutor = candidate.substitutor val initialType = initialSubstitutor.substituteOrSelf(typeRef.type) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt index 3f341a9b674..ebe7a9f0b02 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt @@ -38,8 +38,8 @@ fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean { } } -fun ConeKotlinType.receiverType(expectedTypeRef: FirTypeRef, session: FirSession): ConeKotlinType? { - if (isBuiltinFunctionalType(session) && expectedTypeRef.isExtensionFunctionType(session)) { +fun ConeKotlinType.receiverType(expectedTypeRef: FirTypeRef?, session: FirSession): ConeKotlinType? { + if (isBuiltinFunctionalType(session) && expectedTypeRef?.isExtensionFunctionType(session) == true) { return ((this as ConeClassLikeType).fullyExpandedType(session).typeArguments.first() as ConeKotlinTypeProjection).type } return null @@ -63,7 +63,7 @@ val FirAnonymousFunction.receiverType get() = receiverTypeRef?.coneTypeSafe { resultType = typeRef.substituteTypeRef(subCandidate) - result.argumentList.transformArguments(this, subCandidate.createArgumentsMapping()) - subCandidate.handleVarargs(result.argumentList) - subCandidate.argumentMapping?.let { - result.replaceArgumentList(buildResolvedArgumentList(it)) + val expectedArgumentsTypeMapping = runIf(!calleeReference.isError) { subCandidate.createArgumentsMapping() } + result.argumentList.transformArguments(this, expectedArgumentsTypeMapping) + if (!calleeReference.isError) { + subCandidate.handleVarargs(result.argumentList) + subCandidate.argumentMapping?.let { + result.replaceArgumentList(buildResolvedArgumentList(it)) + } } result.transformExplicitReceiver(integerApproximator, null) } @@ -258,11 +260,7 @@ class FirCallCompletionResultsWriterTransformer( val typeArguments = computeTypeArguments(variableAssignment, calleeReference.candidate) return variableAssignment.transformCalleeReference( StoreCalleeReference, - buildResolvedNamedReference { - source = calleeReference.source - name = calleeReference.name - resolvedSymbol = calleeReference.candidateSymbol - }, + calleeReference.toResolvedReference(), ).transformExplicitReceiver(integerApproximator, null).apply { replaceTypeArguments(typeArguments) }.compose() @@ -310,18 +308,17 @@ class FirCallCompletionResultsWriterTransformer( delegatedConstructorCall.calleeReference as? FirNamedReferenceWithCandidate ?: return delegatedConstructorCall.compose() val subCandidate = calleeReference.candidate - delegatedConstructorCall.argumentList.transformArguments(this, calleeReference.candidate.createArgumentsMapping()) - subCandidate.handleVarargs(delegatedConstructorCall.argumentList) - subCandidate.argumentMapping?.let { - delegatedConstructorCall.replaceArgumentList(buildResolvedArgumentList(it)) + val argumentsMapping = runIf(!calleeReference.isError) { calleeReference.candidate.createArgumentsMapping() } + delegatedConstructorCall.argumentList.transformArguments(this, argumentsMapping) + if (!calleeReference.isError) { + subCandidate.handleVarargs(delegatedConstructorCall.argumentList) + subCandidate.argumentMapping?.let { + delegatedConstructorCall.replaceArgumentList(buildResolvedArgumentList(it)) + } } return delegatedConstructorCall.transformCalleeReference( StoreCalleeReference, - buildResolvedNamedReference { - source = calleeReference.source - name = calleeReference.name - resolvedSymbol = calleeReference.candidateSymbol - }, + calleeReference.toResolvedReference(), ).compose() } @@ -433,11 +430,7 @@ class FirCallCompletionResultsWriterTransformer( return (syntheticCall.transformCalleeReference( StoreCalleeReference, - buildResolvedNamedReference { - source = calleeReference.source - name = calleeReference.name - resolvedSymbol = calleeReference.candidateSymbol - }, + calleeReference.toResolvedReference(), ) as D).compose() } @@ -449,6 +442,20 @@ class FirCallCompletionResultsWriterTransformer( val expectedType = data?.getExpectedType(constExpression) return constExpression.transform(integerApproximator, expectedType) } + + private fun FirNamedReferenceWithCandidate.toResolvedReference() = if (this is FirErrorReferenceWithCandidate) { + buildErrorNamedReference { + source = this@toResolvedReference.source + diagnostic = this@toResolvedReference.diagnostic + } + } else { + buildResolvedNamedReference { + source = this@toResolvedReference.source + name = this@toResolvedReference.name + resolvedSymbol = this@toResolvedReference.candidateSymbol + } + } + } sealed class ExpectedArgumentType { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 33633612f39..329cad93a3e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -220,12 +220,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform // name.invoke() case callCompleter.completeCall(resultExplicitReceiver, noExpectedType) } - val completionResult = callCompleter.completeCall(resultExpression, expectedTypeRef) - - if (completionResult.result.typeRef is FirErrorTypeRef) { - completionResult.result.argumentList.transformArguments(transformer, ResolutionMode.LambdaResolution(null)) - } - completionResult + callCompleter.completeCall(resultExpression, expectedTypeRef) } catch (e: ProcessCanceledException) { throw e } catch (e: Throwable) { diff --git a/compiler/testData/diagnostics/tests/inference/recursiveLocalFuns/selfCall.fir.kt b/compiler/testData/diagnostics/tests/inference/recursiveLocalFuns/selfCall.fir.kt index 4bddc08a208..b8269f29987 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveLocalFuns/selfCall.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveLocalFuns/selfCall.fir.kt @@ -2,7 +2,7 @@ fun foo() { fun bar1() = bar1() - fun bar2() = 1 + bar2() + fun bar2() = 1 + bar2() fun bar3() = id(bar3()) } diff --git a/compiler/testData/diagnostics/tests/regressions/kt10843.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt10843.fir.kt index c34a25f506f..d8b434aa4a4 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt10843.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt10843.fir.kt @@ -3,6 +3,6 @@ // See EA-76890 / KT-10843: NPE during analysis fun lambda(x : Int?) = x?.let l { y -> - if (y > 0) return@l x + if (y > 0) return@l x y }!! diff --git a/compiler/testData/ir/irText/expressions/callableReferences/adaptedExtensionFunctions.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/adaptedExtensionFunctions.fir.txt index 4bb1fc0c7b7..544e408c4a8 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/adaptedExtensionFunctions.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/adaptedExtensionFunctions.fir.txt @@ -52,4 +52,4 @@ FILE fqName: fileName:/adaptedExtensionFunctions.kt FUN name:testExtensionBoth visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUNCTION_REFERENCE 'public final fun extensionBoth (i: kotlin.Int, s: kotlin.String, vararg t: kotlin.String): kotlin.Unit declared in ' type=kotlin.reflect.KFunction3<.C, kotlin.Int, kotlin.Array, kotlin.Unit> origin=null reflectionTarget= + FUNCTION_REFERENCE 'public final fun extensionBoth (i: kotlin.Int, s: kotlin.String, vararg t: kotlin.String): kotlin.Unit declared in ' type=kotlin.reflect.KFunction4<.C, kotlin.Int, kotlin.String, kotlin.Array, kotlin.Unit> origin=null reflectionTarget= diff --git a/compiler/testData/ir/irText/expressions/callableReferences/boundInlineAdaptedReference.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/boundInlineAdaptedReference.fir.txt index acf9f10ba56..497ce2c4985 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/boundInlineAdaptedReference.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/boundInlineAdaptedReference.fir.txt @@ -14,5 +14,5 @@ FILE fqName:test fileName:/boundInlineAdaptedReference.kt FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUNCTION_REFERENCE 'public final fun id (s: kotlin.String, vararg xs: kotlin.Int): kotlin.String declared in test' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= + FUNCTION_REFERENCE 'public final fun id (s: kotlin.String, vararg xs: kotlin.Int): kotlin.String declared in test' type=kotlin.reflect.KFunction2 origin=null reflectionTarget= $receiver: CONST String type=kotlin.String value="Fail" diff --git a/compiler/testData/ir/irText/expressions/callableReferences/suspendConversion.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/suspendConversion.fir.txt index ebeea134d75..f5cf106b38a 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/suspendConversion.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/suspendConversion.fir.txt @@ -80,7 +80,7 @@ FILE fqName: fileName:/suspendConversion.kt FUN name:testWithDefaults visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUNCTION_REFERENCE 'public final fun foo4 (i: kotlin.Int): kotlin.Unit declared in ' type=kotlin.reflect.KFunction0 origin=null reflectionTarget= + FUNCTION_REFERENCE 'public final fun foo4 (i: kotlin.Int): kotlin.Unit declared in ' type=kotlin.reflect.KFunction1 origin=null reflectionTarget= FUN name:testWithBoundReceiver visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY ERROR_CALL 'Unresolved reference: #' type=IrErrorType diff --git a/compiler/testData/ir/irText/regressions/typeParametersInImplicitCast.fir.txt b/compiler/testData/ir/irText/regressions/typeParametersInImplicitCast.fir.txt index 7c7f6738689..5112ea50299 100644 --- a/compiler/testData/ir/irText/regressions/typeParametersInImplicitCast.fir.txt +++ b/compiler/testData/ir/irText/regressions/typeParametersInImplicitCast.fir.txt @@ -5,10 +5,10 @@ FILE fqName: fileName:/typeParametersInImplicitCast.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun problematic (lss: kotlin.collections.List.problematic>>): kotlin.collections.List.problematic> declared in ' ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUN_EXPR type=kotlin.Function0> origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.collections.List + FUN_EXPR type=kotlin.Function0> origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.collections.List BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (): kotlin.collections.List declared in .problematic' - CALL 'public/*package*/ open fun id (v: kotlin.collections.List.ListId.id?>?): kotlin.collections.List.ListId.id?> declared in .ListId' type=kotlin.collections.List origin=null - : kotlin.Nothing + RETURN type=kotlin.Nothing from='local final fun (): kotlin.collections.List declared in .problematic' + CALL 'public/*package*/ open fun id (v: kotlin.collections.List.ListId.id?>?): kotlin.collections.List.ListId.id?> declared in .ListId' type=kotlin.collections.List origin=null + : kotlin.Any? v: ERROR_CALL 'Unresolved reference: #' type=IrErrorType diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/31.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/31.fir.kt index a04223fb4f2..c43ed9e5002 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/31.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/31.fir.kt @@ -8,5 +8,5 @@ fun case_1(x: Interface2) = x fun case_1() { val x: Interface1 = null as Interface1 x as Interface2 - case_1(x) + case_1(x) } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/32.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/32.fir.kt index 219a3013cf9..d9ef014fb22 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/32.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/32.fir.kt @@ -37,7 +37,7 @@ fun case_2(x: Int?, y: Nothing?) { fun case_3(x: Int?) { if (x == null) { x as Int - stringArg(x) + stringArg(x) x } } @@ -50,7 +50,7 @@ fun case_3(x: Int?) { fun case_4(x: Int?) { if (x == null) { x!! - stringArg(x) + stringArg(x) x } } @@ -64,7 +64,7 @@ fun case_5(x: Int?) { if (x == null) { var y = x y!! - stringArg(y) + stringArg(y) y } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/2.fir.kt index 47023573897..e173cf04fe7 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/2.fir.kt @@ -298,7 +298,7 @@ fun case_12(a: ((Float) -> Int?)?, b: Float?, c: Boolean?) { if (true && a == null == true || b == null == true) { } else { - val x = a(b) + val x = a(b) ?")!>a.equals(null) ?")!>a.propT ?")!>a.propAny diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt index 5843594a12a..e92847cd63d 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt @@ -161,4 +161,6 @@ inline fun Iterable.same(extractor: (T) -> R): Boolean { } } return true -} \ No newline at end of file +} + +inline fun runIf(condition: Boolean, block: () -> R): R? = if (condition) block() else null \ No newline at end of file