From c75d2c05f017a728e99fc5633054178d7b32f38b Mon Sep 17 00:00:00 2001 From: Andrey Zinovyev Date: Mon, 8 Feb 2021 10:11:50 +0300 Subject: [PATCH 001/153] [KAPT] Correct type for property with accessor ^KT-39060 Fixed --- .../kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt | 4 ++-- .../kapt3-compiler/testData/converter/nonExistentClass.kt | 4 +++- .../kapt3-compiler/testData/converter/nonExistentClass.txt | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index 3b414ca500a..b4d341740d8 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -1023,10 +1023,10 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati val returnType = getNonErrorType( descriptor.returnType, RETURN_TYPE, ktTypeProvider = { - val element = kaptContext.origins[method]?.element - when (element) { + when (val element = kaptContext.origins[method]?.element) { is KtFunction -> element.typeReference is KtProperty -> if (descriptor is PropertyGetterDescriptor) element.typeReference else null + is KtPropertyAccessor -> if (descriptor is PropertyGetterDescriptor) element.property.typeReference else null is KtParameter -> if (descriptor is PropertyGetterDescriptor) element.typeReference else null else -> null } diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/nonExistentClass.kt b/plugins/kapt3/kapt3-compiler/testData/converter/nonExistentClass.kt index ba54f7c0676..9f86ee574cc 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/nonExistentClass.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/nonExistentClass.kt @@ -8,7 +8,9 @@ object NonExistentType { val b: List? = null val c: (ABCDEF) -> Unit = { f -> } val d: ABCDEF) -> Unit>? = null + + val foo: Foo get() = Foo() fun a(a: ABCDEF, s: String): ABCDEF {} fun b(s: String): ABCDEF {} -} \ No newline at end of file +} diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/nonExistentClass.txt b/plugins/kapt3/kapt3-compiler/testData/converter/nonExistentClass.txt index 48b215d42b8..292f74b2bc9 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/nonExistentClass.txt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/nonExistentClass.txt @@ -38,6 +38,11 @@ public final class NonExistentType { return null; } + @org.jetbrains.annotations.NotNull() + public final Foo getFoo() { + return null; + } + @org.jetbrains.annotations.NotNull() public final ABCDEF a(@org.jetbrains.annotations.NotNull() ABCDEF a, @org.jetbrains.annotations.NotNull() From f9e5584a3e7e8de808503d4384b340349d618d12 Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Thu, 4 Feb 2021 15:31:10 +0300 Subject: [PATCH 002/153] Report error about uninferred type parameter for all `CallForImplicitInvoke` psi calls ^KT-44368 Fixed --- .../FirOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ .../calls/DiagnosticReporterByTrackingStrategy.kt | 10 ++++++++-- .../errorsOnImplicitInvokeInSimpleCall.fir.kt | 4 ++++ .../inference/errorsOnImplicitInvokeInSimpleCall.kt | 4 ++++ .../inference/errorsOnImplicitInvokeInSimpleCall.txt | 5 +++++ .../kotlin/test/runners/DiagnosticTestGenerated.java | 6 ++++++ 6 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.kt create mode 100644 compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.txt 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 e0d4ca07cfb..6b86afa4a42 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 @@ -11835,6 +11835,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/equalitySubstitutionInsideNonInvariantType.kt"); } + @Test + @TestMetadata("errorsOnImplicitInvokeInSimpleCall.kt") + public void testErrorsOnImplicitInvokeInSimpleCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.kt"); + } + @Test @TestMetadata("expectedTypeAdditionalTest.kt") public void testExpectedTypeAdditionalTest() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index 4827e3e4d9a..7398559c52d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -446,8 +446,14 @@ class DiagnosticReporterByTrackingStrategy( if (isDiagnosticRedundant) return val expression = when (val atom = error.resolvedAtom.atom) { - is PSIKotlinCallForInvoke -> (atom.psiCall as? CallTransformer.CallForImplicitInvoke)?.outerCall?.calleeExpression - is PSIKotlinCall -> atom.psiCall.calleeExpression + is PSIKotlinCall -> { + val psiCall = atom.psiCall + if (psiCall is CallTransformer.CallForImplicitInvoke) { + psiCall.outerCall.calleeExpression + } else { + psiCall.calleeExpression + } + } is PSIKotlinCallArgument -> atom.valueArgument.getArgumentExpression() else -> call.calleeExpression } ?: return diff --git a/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.fir.kt b/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.fir.kt new file mode 100644 index 00000000000..a8ab368233b --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.fir.kt @@ -0,0 +1,4 @@ +inline operator fun Int.invoke() = this + +val a2 = 1() +val a3 = 1.invoke() diff --git a/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.kt b/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.kt new file mode 100644 index 00000000000..58dd705eb14 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.kt @@ -0,0 +1,4 @@ +inline operator fun Int.invoke() = this + +val a2 = 1() +val a3 = 1.invoke() diff --git a/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.txt b/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.txt new file mode 100644 index 00000000000..716eb401e26 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.txt @@ -0,0 +1,5 @@ +package + +public val a2: kotlin.Int +public val a3: kotlin.Int +public inline operator fun kotlin.Int.invoke(): kotlin.Int 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 32e1253c1d5..197f76038e4 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 @@ -11841,6 +11841,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/equalitySubstitutionInsideNonInvariantType.kt"); } + @Test + @TestMetadata("errorsOnImplicitInvokeInSimpleCall.kt") + public void testErrorsOnImplicitInvokeInSimpleCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/errorsOnImplicitInvokeInSimpleCall.kt"); + } + @Test @TestMetadata("expectedTypeAdditionalTest.kt") public void testExpectedTypeAdditionalTest() throws Exception { From 04017b00a14044cec93fb7734e112f3cce17168c Mon Sep 17 00:00:00 2001 From: Igor Yakovlev Date: Fri, 5 Feb 2021 16:15:46 +0300 Subject: [PATCH 003/153] [FIR IDE] Fix TypeRef resolve to error type caused by invalid number of arguments --- .../FirReferenceResolveTestGenerated.java | 5 +++++ .../idea/references/FirReferenceResolveHelper.kt | 16 +++++++++++++--- .../references/WrongNumberOfTypeArguments3.kt | 9 +++++++++ .../resolve/ReferenceResolveTestGenerated.java | 5 +++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 idea/testData/resolve/references/WrongNumberOfTypeArguments3.kt diff --git a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/resolve/FirReferenceResolveTestGenerated.java b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/resolve/FirReferenceResolveTestGenerated.java index 41ae5fa3fbd..7cfd514a251 100644 --- a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/resolve/FirReferenceResolveTestGenerated.java +++ b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/resolve/FirReferenceResolveTestGenerated.java @@ -429,6 +429,11 @@ public class FirReferenceResolveTestGenerated extends AbstractFirReferenceResolv runTest("idea/testData/resolve/references/WrongNumberOfTypeArguments2.kt"); } + @TestMetadata("WrongNumberOfTypeArguments3.kt") + public void testWrongNumberOfTypeArguments3() throws Exception { + runTest("idea/testData/resolve/references/WrongNumberOfTypeArguments3.kt"); + } + @TestMetadata("WrongNumberOfTypeArgumentsInSupertype.kt") public void testWrongNumberOfTypeArgumentsInSupertype() throws Exception { runTest("idea/testData/resolve/references/WrongNumberOfTypeArgumentsInSupertype.kt"); diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt index 85621f74508..9c207087f4f 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt @@ -16,14 +16,17 @@ import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOperatorAmbiguityError +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeWrongNumberOfTypeArgumentsError import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType +import org.jetbrains.kotlin.fir.types.FirErrorTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.classId -import org.jetbrains.kotlin.idea.fir.* +import org.jetbrains.kotlin.idea.fir.getCandidateSymbols +import org.jetbrains.kotlin.idea.fir.isImplicitFunctionCall import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession @@ -42,8 +45,15 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult internal object FirReferenceResolveHelper { fun FirResolvedTypeRef.toTargetSymbol(session: FirSession, symbolBuilder: KtSymbolByFirBuilder): KtSymbol? { - val type = type as? ConeLookupTagBasedType ?: return null - val symbol = type.lookupTag.toSymbol(session) as? AbstractFirBasedSymbol<*> + + val type = type as? ConeLookupTagBasedType + val resolvedSymbol = type?.lookupTag?.toSymbol(session) as? AbstractFirBasedSymbol<*> + + val symbol = resolvedSymbol ?: run { + val diagnostic = (this as? FirErrorTypeRef)?.diagnostic + (diagnostic as? ConeWrongNumberOfTypeArgumentsError)?.type + } + return symbol?.fir?.buildSymbol(symbolBuilder) } diff --git a/idea/testData/resolve/references/WrongNumberOfTypeArguments3.kt b/idea/testData/resolve/references/WrongNumberOfTypeArguments3.kt new file mode 100644 index 00000000000..040d61195d8 --- /dev/null +++ b/idea/testData/resolve/references/WrongNumberOfTypeArguments3.kt @@ -0,0 +1,9 @@ +package foo + +class CC +class DD + +val v1 = DDC> + +// REF1: (foo).DD +// REF2: (foo).CC diff --git a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java index 0ad7563c22b..b5fcd41ad55 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java @@ -429,6 +429,11 @@ public class ReferenceResolveTestGenerated extends AbstractReferenceResolveTest runTest("idea/testData/resolve/references/WrongNumberOfTypeArguments2.kt"); } + @TestMetadata("WrongNumberOfTypeArguments3.kt") + public void testWrongNumberOfTypeArguments3() throws Exception { + runTest("idea/testData/resolve/references/WrongNumberOfTypeArguments3.kt"); + } + @TestMetadata("WrongNumberOfTypeArgumentsInSupertype.kt") public void testWrongNumberOfTypeArgumentsInSupertype() throws Exception { runTest("idea/testData/resolve/references/WrongNumberOfTypeArgumentsInSupertype.kt"); From 0e8f4294f09444213f670b7454d72e8c7e8d8dba Mon Sep 17 00:00:00 2001 From: Margarita Bobova Date: Mon, 8 Feb 2021 12:16:00 +0300 Subject: [PATCH 004/153] Add changelog for 1.4.30 --- ChangeLog.md | 138 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 17 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 4f7905ace3a..3732d6cb14d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,7 +1,7 @@ # CHANGELOG -## 1.4.30-M1 +## 1.4.30 ### Android @@ -13,23 +13,20 @@ - [`KT-42234`](https://youtrack.jetbrains.com/issue/KT-42234) Move LLVM optimization parameters into konan.properties - [`KT-42649`](https://youtrack.jetbrains.com/issue/KT-42649) IndexOutOfBoundsException during InlineClassTransformer lowering - [`KT-42942`](https://youtrack.jetbrains.com/issue/KT-42942) Native: optimize peak backend memory by clearing BindingContext after psi2ir -- [`KT-43198`](https://youtrack.jetbrains.com/issue/KT-43198) init blocks inside inline classes -- [`KT-31072`](https://youtrack.jetbrains.com/issue/KT-31072) Don't use non-reified arguments to specialize type operations in IR inliner - -### Backend. JS -- [`KT-41227`](https://youtrack.jetbrains.com/issue/KT-41227) KJS IR: don't copy to child's prototype references to the function from parent - -### Backend. IR -- [`KT-41227`](https://youtrack.jetbrains.com/issue/KT-41227) KJS IR: don't copy to child's prototype references to the function from parent +- [`KT-43198`](https://youtrack.jetbrains.com/issue/KT-43198) Native: support `init` blocks inside inline classes ### Compiler #### New Features -- [`KT-28055`](https://youtrack.jetbrains.com/issue/KT-28055) Consider supporting `init` blocks inside inline classes +- [`KT-28055`](https://youtrack.jetbrains.com/issue/KT-28055) Support `init` blocks inside inline classes - [`KT-28056`](https://youtrack.jetbrains.com/issue/KT-28056) Consider supporting non-public primary constructors for inline classes +- [`KT-41265`](https://youtrack.jetbrains.com/issue/KT-41265) Support noarg compiler plugin for JVM IR - [`KT-42094`](https://youtrack.jetbrains.com/issue/KT-42094) Allow open callable members in expect interfaces - [`KT-43129`](https://youtrack.jetbrains.com/issue/KT-43129) FIR: Support OverloadResolutionByLambdaReturnType +- [`KT-43592`](https://youtrack.jetbrains.com/issue/KT-43592) Promote JVM IR compiler backend to Beta +- [`KT-43919`](https://youtrack.jetbrains.com/issue/KT-43919) Support loading Java annotations on base classes and implementing interfaces' type arguments +- [`KT-44021`](https://youtrack.jetbrains.com/issue/KT-44021) Enable JVM IR backend by default in 1.5 #### Performance Improvements @@ -40,12 +37,25 @@ #### Fixes +- [`KT-11454`](https://youtrack.jetbrains.com/issue/KT-11454) Load annotations on TYPE_USE/TYPE_PARAMETER positions from Java class-files +- [`KT-11732`](https://youtrack.jetbrains.com/issue/KT-11732) Verify error for generic interface method invocation with default parameters +- [`KT-14612`](https://youtrack.jetbrains.com/issue/KT-14612) "ISE: Recursive call in a lazy value" during processing of a (weakly) recursive type alias +- [`KT-18344`](https://youtrack.jetbrains.com/issue/KT-18344) Upper bound of a typealias type parameter is not reported correctly if it contains the typealias itself +- [`KT-18768`](https://youtrack.jetbrains.com/issue/KT-18768) @Notnull annotation from Java does not work with varargs +- [`KT-20548`](https://youtrack.jetbrains.com/issue/KT-20548) java.lang.IllegalStateException: Illegal class container on simple Java code parsing - [`KT-22465`](https://youtrack.jetbrains.com/issue/KT-22465) Excessive synthetic method for private setter from superclass +- [`KT-23816`](https://youtrack.jetbrains.com/issue/KT-23816) Inline classes: constants and annotations +- [`KT-24158`](https://youtrack.jetbrains.com/issue/KT-24158) AE: No receiver found on incomplete code with $-signs +- [`KT-24392`](https://youtrack.jetbrains.com/issue/KT-24392) Nullability of Java arrays is read incorrectly if @Nullable annotation has both targets TYPE_USE and VALUE_PARAMETER - [`KT-26229`](https://youtrack.jetbrains.com/issue/KT-26229) Lambda/anonymous function argument in parentheses is not supported for callsInPlace effect +- [`KT-29735`](https://youtrack.jetbrains.com/issue/KT-29735) KNPE at `KtEnumEntrySuperclassReferenceExpression.getReferencedElement` with explicit type argument inside enum member constructor +- [`KT-31389`](https://youtrack.jetbrains.com/issue/KT-31389) ClassFormatError with companion object in annotation with @JvmStatic +- [`KT-31907`](https://youtrack.jetbrains.com/issue/KT-31907) ISE: UNIT_EXPECTED_TYPE on parsing array literal inside lambda with Unit return type - [`KT-32228`](https://youtrack.jetbrains.com/issue/KT-32228) Inconsistent boxing/unboxing for inline classes when interface is specialized by object expression - [`KT-32450`](https://youtrack.jetbrains.com/issue/KT-32450) Inline class incorrectly gets re-wrapped when provided to a function - [`KT-35849`](https://youtrack.jetbrains.com/issue/KT-35849) Missing nullability assertion on lambda return value if expected type has generic return value type - [`KT-35902`](https://youtrack.jetbrains.com/issue/KT-35902) Kotlin generates a private parameterless constructor for constructors taking inline class arguments with default values +- [`KT-36399`](https://youtrack.jetbrains.com/issue/KT-36399) Gradually support TYPE_USE nullability annotations read from class-files - [`KT-36769`](https://youtrack.jetbrains.com/issue/KT-36769) JVM IR: Missing LVT entries for inline function (default) parameters at call site - [`KT-36982`](https://youtrack.jetbrains.com/issue/KT-36982) JVM IR: SAM adapter classes are generated as synthetic - [`KT-37007`](https://youtrack.jetbrains.com/issue/KT-37007) JVM IR: extraneous property accessors are generated in multifile facade for InlineOnly property @@ -57,11 +67,18 @@ - [`KT-39709`](https://youtrack.jetbrains.com/issue/KT-39709) [FIR] False positive UNINITIALIZED_VARIABLE in presence of complex graph with jumps - [`KT-39923`](https://youtrack.jetbrains.com/issue/KT-39923) Result.Failure will get wrapped with Success when using with RxJava - [`KT-40198`](https://youtrack.jetbrains.com/issue/KT-40198) '$default' methods in 'kotlin/test/AssertionsKt' generated as non-synthetic by JVM_IR +- [`KT-40200`](https://youtrack.jetbrains.com/issue/KT-40200) IDE: Multiple top-level main functions in different files: broken highlighting, "No descriptor resolved for FUN" - [`KT-40262`](https://youtrack.jetbrains.com/issue/KT-40262) ACC_DEPRECATED flag not generated for property getter delegate in multifile class facade in JVM_IR - [`KT-40282`](https://youtrack.jetbrains.com/issue/KT-40282) Inline class wrapping Any gets double boxed - [`KT-40464`](https://youtrack.jetbrains.com/issue/KT-40464) JVM_IR does not generate LINENUMBER at closing brace of (suspend) lambda +- [`KT-40500`](https://youtrack.jetbrains.com/issue/KT-40500) Warnings reporting by Java nullability annotations doesn't work for not top-level types +- [`KT-40926`](https://youtrack.jetbrains.com/issue/KT-40926) IDE import actions do not add required import for convention `invoke()` extension call - [`KT-40948`](https://youtrack.jetbrains.com/issue/KT-40948) IllegalAccessError while initializing val property in EXACTLY_ONCE lambda that is passed to another function +- [`KT-40991`](https://youtrack.jetbrains.com/issue/KT-40991) NI: UNRESOLVED_REFERENCE_WRONG_RECEIVER instead of FUNCTION_EXPECTED with convention `invoke` call +- [`KT-41163`](https://youtrack.jetbrains.com/issue/KT-41163) Double wrapped value in Result class after map operation +- [`KT-41284`](https://youtrack.jetbrains.com/issue/KT-41284) Spring CGLIB proxies break auto-generated data class componentN and copy methods when using JVM IR - [`KT-41468`](https://youtrack.jetbrains.com/issue/KT-41468) JVM IR: IllegalAccessError on access to abstract base member from another package, from anonymous object inside abstract class +- [`KT-41491`](https://youtrack.jetbrains.com/issue/KT-41491) UNRESOLVED_REFERENCE_WRONG_RECEIVER instead of FUNCTION_EXPECTED when invoking non-functional value as a function - [`KT-41493`](https://youtrack.jetbrains.com/issue/KT-41493) JVM IR: names of classes for local delegated variables contain the variable name twice - [`KT-41792`](https://youtrack.jetbrains.com/issue/KT-41792) [FIR] Introduce & use ConeAttribute.UnsafeVariance - [`KT-41793`](https://youtrack.jetbrains.com/issue/KT-41793) [FIR] Make captured types accessible at the end of resolve @@ -70,13 +87,16 @@ - [`KT-41841`](https://youtrack.jetbrains.com/issue/KT-41841) JVM IR: delegates for private functions with default arguments are generated in multifile classes - [`KT-41857`](https://youtrack.jetbrains.com/issue/KT-41857) Flaky 'ConcurrentModificationException' through `kotlin.serialization.DescriptorSerializer` - [`KT-41903`](https://youtrack.jetbrains.com/issue/KT-41903) JVM IR: do not generate LineNumberTable in auto-generated members of data classes +- [`KT-41911`](https://youtrack.jetbrains.com/issue/KT-41911) JVM IR: nested big-arity function calls are not lowered - [`KT-41957`](https://youtrack.jetbrains.com/issue/KT-41957) JVM IR: step into suspend function goes to the first line of the file - [`KT-41960`](https://youtrack.jetbrains.com/issue/KT-41960) JVM IR: smart step into members implemented with delegation to interface doesn't work - [`KT-41961`](https://youtrack.jetbrains.com/issue/KT-41961) JVM IR: line numbers are not generated in JvmMultifileClass facade declarations - [`KT-41962`](https://youtrack.jetbrains.com/issue/KT-41962) JVM IR: intermittent -1 line numbers in the state machine cause double stepping in the debugger +- [`KT-42001`](https://youtrack.jetbrains.com/issue/KT-42001) Cannot resolve symbol: AssertionError: Module is not contained in his own dependencies - [`KT-42002`](https://youtrack.jetbrains.com/issue/KT-42002) JVM / IR: IllegalStateException: "No mapping for symbol: VAR IR_TEMPORARY_VARIABLE" caused by named arguments - [`KT-42021`](https://youtrack.jetbrains.com/issue/KT-42021) JVM / IR: "IndexOutOfBoundsException: Index 0 out of bounds for length 0" during IR lowering with suspend conversion - [`KT-42033`](https://youtrack.jetbrains.com/issue/KT-42033) JVM IR: accidental override in Map subclass with custom implementations of some members +- [`KT-42036`](https://youtrack.jetbrains.com/issue/KT-42036) IR: "AssertionError: TypeAliasDescriptor expected: deserialized class Nothing" when referencing typealias with @UnsafeVariance - [`KT-42043`](https://youtrack.jetbrains.com/issue/KT-42043) JVM IR: Don't generate collection stubs when implementing methods with more specific return types - [`KT-42044`](https://youtrack.jetbrains.com/issue/KT-42044) Compiler error when lambda with contract surrounded with parentheses - [`KT-42114`](https://youtrack.jetbrains.com/issue/KT-42114) JVM_IR generates stub for 'removeIf' in abstract classes implementing 'List' and 'Set' @@ -103,7 +123,9 @@ - [`KT-42384`](https://youtrack.jetbrains.com/issue/KT-42384) FIR (BE): top-level field has no parent class in BE - [`KT-42496`](https://youtrack.jetbrains.com/issue/KT-42496) FIR resolve: synthetic property is written but has no setter - [`KT-42517`](https://youtrack.jetbrains.com/issue/KT-42517) FIR: exception in BE for recursive inline call +- [`KT-42530`](https://youtrack.jetbrains.com/issue/KT-42530) "AssertionError: No type for resolved lambda argument" on attempting to assign a Pair to a couple of values in a scratch file - [`KT-42601`](https://youtrack.jetbrains.com/issue/KT-42601) [FIR] Inherited declaration clash for stdlib inheritors +- [`KT-42622`](https://youtrack.jetbrains.com/issue/KT-42622) NI: IllegalStateException for if expression with method reference inside flow - [`KT-42642`](https://youtrack.jetbrains.com/issue/KT-42642) ISE: No `getProgressionLastElement` for progression type IntProgressionType - [`KT-42650`](https://youtrack.jetbrains.com/issue/KT-42650) JVM IR: extraneous nullability annotation on a generic function of a flexible type - [`KT-42656`](https://youtrack.jetbrains.com/issue/KT-42656) FIR2IR: unsupported callable reference for Java field @@ -117,6 +139,8 @@ - [`KT-42933`](https://youtrack.jetbrains.com/issue/KT-42933) JVM / IR: "AnalyzerException: Expected an object reference, but found I" with local delegate in inline class - [`KT-43006`](https://youtrack.jetbrains.com/issue/KT-43006) JVM/JVM_IR: do not generate no-arg constructor for constructor with default arguments if there are inline class types in the signature - [`KT-43017`](https://youtrack.jetbrains.com/issue/KT-43017) JVM / IR: AssertionError when callable reference passed into a function requiring a suspendable function +- [`KT-43051`](https://youtrack.jetbrains.com/issue/KT-43051) JVM IR: extraneous methods overridding default (Java 8) collection methods in inline class that extends MutableList +- [`KT-43067`](https://youtrack.jetbrains.com/issue/KT-43067) Inner class declaration inside inline class should be prohibited - [`KT-43068`](https://youtrack.jetbrains.com/issue/KT-43068) JVM IR: no generic signatures for explicitly written methods in a List subclass, whose signature coincides with MutableList methods - [`KT-43132`](https://youtrack.jetbrains.com/issue/KT-43132) JVM / IR: Method name '' in class '...$screenTexts$1$1' cannot be represented in dex format. - [`KT-43145`](https://youtrack.jetbrains.com/issue/KT-43145) JVM IR: $default methods in multi-file facades are generated as non-synthetic final @@ -125,6 +149,7 @@ - [`KT-43199`](https://youtrack.jetbrains.com/issue/KT-43199) JVM IR: synthetic flag for deprecated-hidden is not generated for DeprecatedSinceKotlin and deprecation from override - [`KT-43207`](https://youtrack.jetbrains.com/issue/KT-43207) JVM IR: no collection stub for `iterator` is generated on extending AbstractCollection - [`KT-43217`](https://youtrack.jetbrains.com/issue/KT-43217) JVM_IR: Multiple FAKE_OVERRIDES for java methods using @NonNull Double and java double +- [`KT-43225`](https://youtrack.jetbrains.com/issue/KT-43225) Confusing message of warning NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER - [`KT-43226`](https://youtrack.jetbrains.com/issue/KT-43226) "Incompatible stack heights" with non-local return to outer lambda inside suspend lambda - [`KT-43242`](https://youtrack.jetbrains.com/issue/KT-43242) JVM / IR: "AnalyzerException: Expected I, but found R" caused by `when` inside object with @Nullable Integer subject - [`KT-43249`](https://youtrack.jetbrains.com/issue/KT-43249) Wrong code generated for suspend lambdas with inline class parameters @@ -133,25 +158,59 @@ - [`KT-43327`](https://youtrack.jetbrains.com/issue/KT-43327) JVM_IR: No deprecated or synthetic flag for accessors of deprecated-hidden property of unsigned type - [`KT-43332`](https://youtrack.jetbrains.com/issue/KT-43332) FIR: Smart casts lead to false-positive ambiguity - [`KT-43370`](https://youtrack.jetbrains.com/issue/KT-43370) JVM IR: No deprecated flag for getter of deprecated property copied via delegation by interface +- [`KT-43459`](https://youtrack.jetbrains.com/issue/KT-43459) JVM_IR. Wrong signature for synthetic $annotations method for extension property on nullable primitive +- [`KT-43478`](https://youtrack.jetbrains.com/issue/KT-43478) NI: "IndexOutOfBoundsException: Index: 3, Size: 3" caused by `is` check with raw type inside `if` condition with `when` inside +- [`KT-43519`](https://youtrack.jetbrains.com/issue/KT-43519) JVM_IR. External functions generated differently in multi file facades +- [`KT-43524`](https://youtrack.jetbrains.com/issue/KT-43524) JVM_IR. Missed deprecation flag on companion @JvmStatic property accessor - [`KT-43525`](https://youtrack.jetbrains.com/issue/KT-43525) Prohibit JvmOverloads on declarations with inline class types in parameters +- [`KT-43536`](https://youtrack.jetbrains.com/issue/KT-43536) JVM IR: IllegalStateException is not caught by runCatching under Deferred.await() with kotlinx.coroutines - [`KT-43562`](https://youtrack.jetbrains.com/issue/KT-43562) JVM IR: incorrect mangling for Collection.size in unsigned arrays - [`KT-43584`](https://youtrack.jetbrains.com/issue/KT-43584) [FIR] Java annotations with named arguments aren't loaded correctly +- [`KT-43587`](https://youtrack.jetbrains.com/issue/KT-43587) Invalid default parameter value in expect actual declaration on jvm +- [`KT-43630`](https://youtrack.jetbrains.com/issue/KT-43630) "AssertionError: Number of arguments should not be less than number of parameters" during capturing intersection raw type with star projection +- [`KT-43698`](https://youtrack.jetbrains.com/issue/KT-43698) NoSuchMethodError for inline class implementing interface with @JvmDefault methods, -Xjvm-default=enable +- [`KT-43741`](https://youtrack.jetbrains.com/issue/KT-43741) Report error on inline class implementing 'kotlin.Cloneable' +- [`KT-43845`](https://youtrack.jetbrains.com/issue/KT-43845) org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Failed to generate expression: KtBlockExpression +- [`KT-43956`](https://youtrack.jetbrains.com/issue/KT-43956) NI: "Error type encountered – UninferredParameterTypeConstructor" on "try" and other constructs with code block as a value +- [`KT-44055`](https://youtrack.jetbrains.com/issue/KT-44055) Left uninferred type parameter for callable references inside special calls +- [`KT-44113`](https://youtrack.jetbrains.com/issue/KT-44113) Compiler frontend exception: Number of arguments should not be less than number of parameters, but: parameters=2, args=1 +- [`KT-44145`](https://youtrack.jetbrains.com/issue/KT-44145) No highlighting for not initialized base constructor and NoSuchMethodError in Android plugin ### IDE +#### New Features + +- [`KT-44075`](https://youtrack.jetbrains.com/issue/KT-44075) Sealed interfaces: New Kotlin Class/File menu update + +#### Fixes + +- [`KT-29454`](https://youtrack.jetbrains.com/issue/KT-29454) Light class with unexpected name when using obfuscated library - [`KT-31553`](https://youtrack.jetbrains.com/issue/KT-31553) Complete Statement: Wrong auto-insertion of closing curly brace for a code block - [`KT-33466`](https://youtrack.jetbrains.com/issue/KT-33466) IDE generates incorrect `external override` with body for overriding `open external` method - [`KT-39458`](https://youtrack.jetbrains.com/issue/KT-39458) Add CLI support for UL classes - [`KT-40403`](https://youtrack.jetbrains.com/issue/KT-40403) UAST: PsiMethod for invoked extension function/property misses `@receiver:` annotations - [`KT-41406`](https://youtrack.jetbrains.com/issue/KT-41406) Kotlin doesn't report annotations for type arguments (no way to add `@Nls`, `@NonNls` annotations to String collections in Kotlin) - [`KT-41420`](https://youtrack.jetbrains.com/issue/KT-41420) UAST does not return information about type annotations +- [`KT-42194`](https://youtrack.jetbrains.com/issue/KT-42194) OOME: Java heap space from incremental compilation - [`KT-42754`](https://youtrack.jetbrains.com/issue/KT-42754) MPP: no smart cast for Common nullable property used in platform module - [`KT-42821`](https://youtrack.jetbrains.com/issue/KT-42821) MPP, IDE: Platform-specific errors are reported even when build doesn't target that platform +- [`KT-44116`](https://youtrack.jetbrains.com/issue/KT-44116) Add language version 1.5 to the compiler configuration preferences +- [`KT-44523`](https://youtrack.jetbrains.com/issue/KT-44523) IDE notification for trying new JVM backend +- [`KT-44543`](https://youtrack.jetbrains.com/issue/KT-44543) Kotlin's LowMemoryWatcher leaks on Kotlin plugin unload ### IDE. Android - [`KT-42381`](https://youtrack.jetbrains.com/issue/KT-42381) MPP: Bad IDEA dependencies: JVM module depending on built artifact instead of sources of module with Android Plugin applied +### IDE. Completion + +- [`KT-44016`](https://youtrack.jetbrains.com/issue/KT-44016) Code completion: support for "sealed interface" +- [`KT-44250`](https://youtrack.jetbrains.com/issue/KT-44250) Code completion does not work in when expression with sealed type argument + +### IDE. Gradle. Script + +- [`KT-39105`](https://youtrack.jetbrains.com/issue/KT-39105) AE “JvmBuiltins has not been initialized properly” after creating new Gradle/Kotlin-based project via old Project Wizard + ### IDE. Inspections and Intentions #### New Features @@ -162,6 +221,9 @@ - [`KT-34533`](https://youtrack.jetbrains.com/issue/KT-34533) INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER: Add quickfix "Add val to parameter" - [`KT-35215`](https://youtrack.jetbrains.com/issue/KT-35215) Quickfix for CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT to remove `const` modifier - [`KT-40251`](https://youtrack.jetbrains.com/issue/KT-40251) Intention action to evaluate compile time expression +- [`KT-44017`](https://youtrack.jetbrains.com/issue/KT-44017) Sealed interfaces: Java side Inspection "implementation of Kotlin sealed interface is forbidden" +- [`KT-43941`](https://youtrack.jetbrains.com/issue/KT-43941) Sealed interfaces: intention to extend class/interface +- [`KT-44043`](https://youtrack.jetbrains.com/issue/KT-44043) Sealed interfaces: quickfix to move class/interface to proper location #### Fixes @@ -200,10 +262,27 @@ - [`KT-43760`](https://youtrack.jetbrains.com/issue/KT-43760) KJS: Debugging Kotlin code for Node.js runtime doesn't work +### IDE. Misc + +- [`KT-44018`](https://youtrack.jetbrains.com/issue/KT-44018) Sealed interfaces: IDE side implementation for hierarchy provider + +### IDE. Multiplatform + +- [`KT-40814`](https://youtrack.jetbrains.com/issue/KT-40814) MISSING_DEPENDENCY_CLASS when consuming native-shared library in a source-set with fewer targets than library has + +### IDE. Run Configurations + +- [`KT-34535`](https://youtrack.jetbrains.com/issue/KT-34535) Unable to run common tests on Android via gutter icon in a multiplatform project + ### IDE. Scratch +- [`KT-25038`](https://youtrack.jetbrains.com/issue/KT-25038) Scratch: Destructuring declaration produces an unresolved reference - [`KT-43415`](https://youtrack.jetbrains.com/issue/KT-43415) Kotlin scratch file could not be run and could lead to dead lock +### IDE. Script + +- [`KT-44117`](https://youtrack.jetbrains.com/issue/KT-44117) IDE / Scripts: custom kotlin script definitions aren't loaded + ### JavaScript #### Fixes @@ -214,35 +293,37 @@ - [`KT-40686`](https://youtrack.jetbrains.com/issue/KT-40686) KJS: Uncaught ReferenceError caused by external class as type inside eventListener in init block - [`KT-40771`](https://youtrack.jetbrains.com/issue/KT-40771) KJS / IR: "ReferenceError: Metadata is not defined" caused by default parameter value in inner class constructor - [`KT-41032`](https://youtrack.jetbrains.com/issue/KT-41032) KJS / IR: "AssertionError: Assertion failed" caused by class that is delegated to inherited interface +- [`KT-41076`](https://youtrack.jetbrains.com/issue/KT-41076) KJS / IR: "AssertionError: Assertion failed" caused by overridden extensiion function in child class - [`KT-41771`](https://youtrack.jetbrains.com/issue/KT-41771) KJS / IR: IndexOutOfBoundsException "Index 0 out of bounds for length 0" caused by inline class with List in primary constructor and vararg in secondary - [`KT-42025`](https://youtrack.jetbrains.com/issue/KT-42025) KJS / IR: IrConstructorCallImpl: No such type argument slot: 0 - [`KT-42112`](https://youtrack.jetbrains.com/issue/KT-42112) KJS: StackOverflowError on @JsExport in case of name clash with function with Enum parameter with star-projection - [`KT-42262`](https://youtrack.jetbrains.com/issue/KT-42262) KJS: `break`-statements without label are ignored in a `when` +- [`KT-42357`](https://youtrack.jetbrains.com/issue/KT-42357) KotlinJS - external class constructor with vararg does not correctly handle spread operator. - [`KT-42364`](https://youtrack.jetbrains.com/issue/KT-42364) KJS: Properties of interface delegate are non-configurable +- [`KT-43212`](https://youtrack.jetbrains.com/issue/KT-43212) JS IR: support `init` blocks inside inline classes - [`KT-43222`](https://youtrack.jetbrains.com/issue/KT-43222) KJS IR: prototype lazy initialization for top-level properties like in JVM - [`KT-43313`](https://youtrack.jetbrains.com/issue/KT-43313) KJS / IR: "Can't find name for declaration FUN" for secondary constructor +- [`KT-43901`](https://youtrack.jetbrains.com/issue/KT-43901) Call to enum values() method from enum companion object leads to non-initialized enum instances ### KMM Plugin - [`KT-41677`](https://youtrack.jetbrains.com/issue/KT-41677) Could not launch iOS project with custom display name -- [`KT-42463`](https://youtrack.jetbrains.com/issue/KT-42463) Launch common tests on local JVM via run gutter +- [`KT-42463`](https://youtrack.jetbrains.com/issue/KT-42463) Launch common tests for Android on local JVM via run gutter - [`KT-43188`](https://youtrack.jetbrains.com/issue/KT-43188) NoSuchMethodError in New Module Wizard of KMM Project ### Libraries - [`KT-41112`](https://youtrack.jetbrains.com/issue/KT-41112) Docs: add more details about bit shift operations +- [`KT-41278`](https://youtrack.jetbrains.com/issue/KT-41278) map.entries.contains can return false if the argument is not MutableEntry - [`KT-41356`](https://youtrack.jetbrains.com/issue/KT-41356) Incorrect documentation for `rangeTo` function +- [`KT-44456`](https://youtrack.jetbrains.com/issue/KT-44456) Introduce locale-agnostic API for case conversions +- [`KT-44458`](https://youtrack.jetbrains.com/issue/KT-44458) Introduce new Char-to-code and Char-to-digit conversions ### Middle-end. IR - [`KT-41765`](https://youtrack.jetbrains.com/issue/KT-41765) [Native/IR] Could not resolveFakeOverride() - [`KT-42054`](https://youtrack.jetbrains.com/issue/KT-42054) Psi2ir: "RuntimeException: IrSimpleFunctionSymbolImpl is already bound" when using result of function with overload resolution by lambda return type -### Native - -- [`KT-42822`](https://youtrack.jetbrains.com/issue/KT-42822) Kotlin/Native Worker leaks ObjC/Swift autorelease references (and indirectly bridged K/N references) on Darwin targets -- [`KT-42397`](https://youtrack.jetbrains.com/issue/KT-42397) Reverse C interop usage of companion object reports spurious leaks - ### Native. C and ObjC Import - [`KT-42412`](https://youtrack.jetbrains.com/issue/KT-42412) [C-interop] Modality of generated property accessors is always FINAL @@ -250,6 +331,7 @@ ### Native. ObjC Export - [`KT-38530`](https://youtrack.jetbrains.com/issue/KT-38530) Native: values() method of enum classes is not exposed to Objective-C/Swift +- [`KT-43599`](https://youtrack.jetbrains.com/issue/KT-43599) K/N: Unbound symbols not allowed ### Native. Platform libraries @@ -265,6 +347,7 @@ ### Native. Stdlib +- [`KT-42172`](https://youtrack.jetbrains.com/issue/KT-42172) Kotlin/Native: StableRef.dispose race condition on Kotlin deinitRuntime - [`KT-42428`](https://youtrack.jetbrains.com/issue/KT-42428) Inconsistent behavior of map.entries on Kotlin.Native ### Reflection @@ -273,6 +356,7 @@ ### Tools. CLI +- [`KT-43294`](https://youtrack.jetbrains.com/issue/KT-43294) Support `-no-stdlib` option for the `kotlin` runner - [`KT-43406`](https://youtrack.jetbrains.com/issue/KT-43406) JVM: produce deterministic jar files if -d option value is a .jar file ### Tools. CLI. Native @@ -283,6 +367,7 @@ - [`KT-41764`](https://youtrack.jetbrains.com/issue/KT-41764) KJS /IR IllegalStateException: "Symbol for public kotlin/arrayOf is unbound" with serialization plugin - [`KT-42976`](https://youtrack.jetbrains.com/issue/KT-42976) kotlinx.serialization + JVM IR: NPE on annotation with @SerialInfo +- [`KT-43725`](https://youtrack.jetbrains.com/issue/KT-43725) Prohibit inner and local classes in kotlin-noarg ### Tools. Gradle @@ -292,6 +377,8 @@ - [`KT-42058`](https://youtrack.jetbrains.com/issue/KT-42058) Support moduleName option in Kotlin Gradle plugin for JVM - [`KT-43054`](https://youtrack.jetbrains.com/issue/KT-43054) Implementation of `AbstractKotlinTarget#buildAdhocComponentsFromKotlinVariants` breaks configuration caching - [`KT-43489`](https://youtrack.jetbrains.com/issue/KT-43489) Incremental compilation - unable to find history files causing full recompilation +- [`KT-43740`](https://youtrack.jetbrains.com/issue/KT-43740) Gradle out-of-process runner fails with unclear diagnostics if build directory does not exist +- [`KT-43895`](https://youtrack.jetbrains.com/issue/KT-43895) Fix cacheability warnings for the Kotlin plugins ### Tools. Gradle. JS @@ -299,6 +386,10 @@ - [`KT-42462`](https://youtrack.jetbrains.com/issue/KT-42462) NPM dependency declaration with Groovy interpolated string - [`KT-42954`](https://youtrack.jetbrains.com/issue/KT-42954) Kotlin/JS: IDE import after changing `kotlin.js.externals.output.format` does not re-generate externals - [`KT-43535`](https://youtrack.jetbrains.com/issue/KT-43535) Common webpack configuration breaks on lambda serialization in some cases +- [`KT-43668`](https://youtrack.jetbrains.com/issue/KT-43668) PackageJson task use file dependencies as is (files and directories), but only files necessary +- [`KT-43793`](https://youtrack.jetbrains.com/issue/KT-43793) nodeArgs in NodeJsExec task +- [`KT-43842`](https://youtrack.jetbrains.com/issue/KT-43842) KJS: Invalid `output.library` support for `null` value +- [`KT-44104`](https://youtrack.jetbrains.com/issue/KT-44104) KJS / Gradle: An ability to pass jvm args to K2JSDce process ### Tools. Gradle. Multiplatform @@ -306,6 +397,7 @@ - [`KT-42413`](https://youtrack.jetbrains.com/issue/KT-42413) [MPP/gradle] `withJava` breaks build on 1.4.20-M1 - [`KT-43141`](https://youtrack.jetbrains.com/issue/KT-43141) Gradle / Configuration cache: NPE from org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon.getKotlinOptions() on reusing configuration cache for task compileCommonMainKotlinMetadata - [`KT-43329`](https://youtrack.jetbrains.com/issue/KT-43329) Gradle / Configuration cache: IAE “Parameter specified as non-null is null: method KotlinMetadataTargetConfiguratorKt.isCompatibilityMetadataVariantEnabled, parameter $this$isCompatibilityMetadataVariantEnabled” on reusing configuration cache for task compileKotlinMetadata +- [`KT-44298`](https://youtrack.jetbrains.com/issue/KT-44298) Kotlin 1.4.20+ MPP "root" module publication does not include the source JAR that used to be published in the -metadata modules ### Tools. Gradle. Native @@ -315,12 +407,24 @@ - [`KT-42849`](https://youtrack.jetbrains.com/issue/KT-42849) Gradle / Configuration cache: tasks nativeMetadataJar, runReleaseExecutableNative, runDebugExecutableNative are unsupported and fails on reusing configuration cache - [`KT-42938`](https://youtrack.jetbrains.com/issue/KT-42938) CocoaPods Gradle plugin: podBuildDependencies doesn't properly report xcodebuild failures - [`KT-43151`](https://youtrack.jetbrains.com/issue/KT-43151) Gradle / Configuration cache: UPAE “lateinit property binary has not been initialized” on reusing configuration cache for linkDebugExecutableNative, linkDebugTestNative, linkReleaseExecutableNative tasks -- [`KT-40999`](https://youtrack.jetbrains.com/issue/KT-40999) CocoaPods Gradle plugin: Support custom cinterop options when declaring a pod dependency. +- [`KT-43516`](https://youtrack.jetbrains.com/issue/KT-43516) Failed to resolve Kotin library [Multiple Multiplatform modules] + +### Tools. Incremental Compile + +- [`KT-42937`](https://youtrack.jetbrains.com/issue/KT-42937) another compilation fail (problem with compilation caches?) + +### Tools. JPS + +- [`KT-39536`](https://youtrack.jetbrains.com/issue/KT-39536) JPS compilation fails with IOException "storage is already closed" ### Tools. Parcelize - [`KT-41553`](https://youtrack.jetbrains.com/issue/KT-41553) JVM IR, Parcelize: IrStarProjectionImpl cannot be cast to class IrTypeProjection +### Tools. Scripts + +- [`KT-43534`](https://youtrack.jetbrains.com/issue/KT-43534) Allow running "main.kts" script that does not end in a "main.kts" filename (would allow kotlin scripting on GitHub Actions) + ### Tools. kapt - [`KT-34340`](https://youtrack.jetbrains.com/issue/KT-34340) Incremental annotation processor recompile all files (only if KAPT enabled). From 64c5608f3186152044fa79a21a60a09fa2fc947a Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 5 Feb 2021 11:20:57 +0100 Subject: [PATCH 005/153] FIR: expect nullable type for elvis LHS --- .../FirBlackBoxCodegenTestGenerated.java | 6 +++ .../kotlin/fir/resolve/ResolutionMode.kt | 5 +++ ...ControlFlowStatementsResolveTransformer.kt | 15 ++++--- .../box/elvis/ofNonNullableResultType.kt | 7 +++ .../ir/irText/expressions/kt30796.fir.kt.txt | 11 ++--- .../ir/irText/expressions/kt30796.fir.txt | 44 +++++++++---------- .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../IrJsCodegenBoxES6TestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ .../IrCodegenBoxWasmTestGenerated.java | 5 +++ 13 files changed, 91 insertions(+), 34 deletions(-) create mode 100644 compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index eb521be52a6..70f85227e17 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -13644,6 +13644,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @Test + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @Test @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt index 44d33bb116f..e7a0251a093 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt @@ -26,6 +26,11 @@ sealed class ResolutionMode { fun withExpectedType(expectedTypeRef: FirTypeRef?): ResolutionMode = expectedTypeRef?.let { ResolutionMode.WithExpectedType(it) } ?: ResolutionMode.ContextDependent +@JvmName("withExpectedTypeNullable") +fun withExpectedType(coneType: ConeKotlinType?): ResolutionMode { + return coneType?.let { withExpectedType(it) } ?: ResolutionMode.ContextDependent +} + fun withExpectedType(coneType: ConeKotlinType): ResolutionMode { val typeRef = buildResolvedTypeRef { type = coneType diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt index 3864150cf6e..00ab34356f2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve -import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirTargetElement import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind @@ -18,7 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer import org.jetbrains.kotlin.fir.resolve.withExpectedType import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype -import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.compose @@ -228,12 +227,14 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran ): CompositeTransformResult { if (elvisExpression.calleeReference is FirResolvedNamedReference) return elvisExpression.compose() elvisExpression.transformAnnotations(transformer, data) - val expectedArgumentType = - if (data is ResolutionMode.WithExpectedType && data.expectedType !is FirImplicitTypeRef) data - else ResolutionMode.ContextDependent - elvisExpression.transformLhs(transformer, expectedArgumentType) + + val expectedType = data.expectedType?.coneTypeSafe() + val resolutionModeForLhs = withExpectedType(expectedType?.withNullability(ConeNullability.NULLABLE)) + elvisExpression.transformLhs(transformer, resolutionModeForLhs) dataFlowAnalyzer.exitElvisLhs(elvisExpression) - elvisExpression.transformRhs(transformer, expectedArgumentType) + + val resolutionModeForRhs = withExpectedType(expectedType) + elvisExpression.transformRhs(transformer, resolutionModeForRhs) val result = syntheticCallGenerator.generateCalleeForElvisExpression(elvisExpression, resolutionContext)?.let { callCompleter.completeCall(it, data.expectedType).result diff --git a/compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt b/compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt new file mode 100644 index 00000000000..0564ce69ccd --- /dev/null +++ b/compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt @@ -0,0 +1,7 @@ +fun f(): T? = "OK" as? T + +fun g(): Nothing = throw RuntimeException("fail") + +fun h(): T = run { f() } ?: run { g() } + +fun box(): String = h() diff --git a/compiler/testData/ir/irText/expressions/kt30796.fir.kt.txt b/compiler/testData/ir/irText/expressions/kt30796.fir.kt.txt index 78adb7af6f6..067424caa70 100644 --- a/compiler/testData/ir/irText/expressions/kt30796.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/kt30796.fir.kt.txt @@ -50,17 +50,17 @@ fun test(value: T, value2: T) { } } val x5: Any = { // BLOCK - val : Any = magic() + val : Any? = magic() when { EQEQ(arg0 = , arg1 = null) -> 42 else -> } } val x6: Any = { // BLOCK - val : Any = { // BLOCK + val : Any? = { // BLOCK val : T = value when { - EQEQ(arg0 = , arg1 = null) -> magic() + EQEQ(arg0 = , arg1 = null) -> magic() else -> } } @@ -70,8 +70,8 @@ fun test(value: T, value2: T) { } } val x7: Any = { // BLOCK - val : Any = { // BLOCK - val : Any = magic() + val : Any? = { // BLOCK + val : Any? = magic() when { EQEQ(arg0 = , arg1 = null) -> value else -> @@ -83,3 +83,4 @@ fun test(value: T, value2: T) { } } } + diff --git a/compiler/testData/ir/irText/expressions/kt30796.fir.txt b/compiler/testData/ir/irText/expressions/kt30796.fir.txt index 3e33c57eb70..e6aab2f4ce2 100644 --- a/compiler/testData/ir/irText/expressions/kt30796.fir.txt +++ b/compiler/testData/ir/irText/expressions/kt30796.fir.txt @@ -97,65 +97,65 @@ FILE fqName: fileName:/kt30796.kt then: GET_VAR 'val tmp_5: T of .test [val] declared in .test' type=T of .test origin=null VAR name:x5 type:kotlin.Any [val] BLOCK type=kotlin.Any origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Any [val] - CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any origin=null - : kotlin.Any + VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Any? [val] + CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any? origin=null + : kotlin.Any? WHEN type=kotlin.Any origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_7: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + arg0: GET_VAR 'val tmp_7: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null arg1: CONST Null type=kotlin.Nothing? value=null then: CONST Int type=kotlin.Int value=42 BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_7: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + then: GET_VAR 'val tmp_7: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null VAR name:x6 type:kotlin.Any [val] BLOCK type=kotlin.Any origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:kotlin.Any [val] - BLOCK type=kotlin.Any origin=ELVIS + VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:kotlin.Any? [val] + BLOCK type=kotlin.Any? origin=ELVIS VAR IR_TEMPORARY_VARIABLE name:tmp_9 type:T of .test [val] GET_VAR 'value: T of .test declared in .test' type=T of .test origin=null - WHEN type=kotlin.Any origin=ELVIS + WHEN type=kotlin.Any? origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ arg0: GET_VAR 'val tmp_9: T of .test [val] declared in .test' type=T of .test origin=null arg1: CONST Null type=kotlin.Nothing? value=null - then: CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any origin=null - : kotlin.Any + then: CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any? origin=null + : kotlin.Any? BRANCH if: CONST Boolean type=kotlin.Boolean value=true then: GET_VAR 'val tmp_9: T of .test [val] declared in .test' type=T of .test origin=null WHEN type=kotlin.Any origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_8: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + arg0: GET_VAR 'val tmp_8: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null arg1: CONST Null type=kotlin.Nothing? value=null then: CONST Int type=kotlin.Int value=42 BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_8: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + then: GET_VAR 'val tmp_8: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null VAR name:x7 type:kotlin.Any [val] BLOCK type=kotlin.Any origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Any [val] - BLOCK type=kotlin.Any origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_11 type:kotlin.Any [val] - CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any origin=null - : kotlin.Any - WHEN type=kotlin.Any origin=ELVIS + VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Any? [val] + BLOCK type=kotlin.Any? origin=ELVIS + VAR IR_TEMPORARY_VARIABLE name:tmp_11 type:kotlin.Any? [val] + CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any? origin=null + : kotlin.Any? + WHEN type=kotlin.Any? origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_11: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + arg0: GET_VAR 'val tmp_11: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null arg1: CONST Null type=kotlin.Nothing? value=null then: GET_VAR 'value: T of .test declared in .test' type=T of .test origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_11: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + then: GET_VAR 'val tmp_11: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null WHEN type=kotlin.Any origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_10: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + arg0: GET_VAR 'val tmp_10: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null arg1: CONST Null type=kotlin.Nothing? value=null then: CONST Int type=kotlin.Int value=42 BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_10: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + then: GET_VAR 'val tmp_10: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 0d276b1f143..f9d2ebea1ef 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -13644,6 +13644,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @Test + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @Test @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index a5b60776c46..42eaa7c9f1c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -13644,6 +13644,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @Test + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @Test @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 037244e41a9..8b46e23e3fb 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11220,6 +11220,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 616a670a869..610047dfa2a 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -10015,6 +10015,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 037a75ef67b..5ee340ea5bb 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -9500,6 +9500,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 1051675f628..0011f4a413b 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -9500,6 +9500,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index d39ca056001..6d2b6c862c2 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -4549,6 +4549,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); From 065d0c66ab0099d7941dd3a665c3a62cd910fac6 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Wed, 3 Feb 2021 15:02:57 -0800 Subject: [PATCH 006/153] FIR checker: reproduce a false alarm on type mismatch of overridden property --- ...irOldFrontendDiagnosticsTestGenerated.java | 6 +++ .../buildLazyValueForMap.fir.kt | 23 +++++++++++ .../testsWithStdLib/buildLazyValueForMap.kt | 21 ++++++++++ .../testsWithStdLib/buildLazyValueForMap.txt | 40 +++++++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 6 +++ 5 files changed, 96 insertions(+) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.fir.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.txt 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 6b86afa4a42..79364c10df4 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 @@ -30644,6 +30644,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/testsWithStdLib/assignedInSynchronized.kt"); } + @Test + @TestMetadata("buildLazyValueForMap.kt") + public void testBuildLazyValueForMap() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt"); + } + @Test @TestMetadata("CallCompanionProtectedNonStatic.kt") public void testCallCompanionProtectedNonStatic() throws Exception { diff --git a/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.fir.kt new file mode 100644 index 00000000000..d2698163573 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.fir.kt @@ -0,0 +1,23 @@ +// !WITH_NEW_INFERENCE + +interface ClassId + +interface JavaAnnotation { + val classId: ClassId? +} + +interface JavaAnnotationOwner { + val annotations: Collection +} + +interface MapBasedJavaAnnotationOwner : JavaAnnotationOwner { + val annotationsByFqNameHash: Map +} + +fun JavaAnnotationOwner.buildLazyValueForMap() = lazy { + annotations.associateBy { it.classId?.hashCode() } +} + +abstract class BinaryJavaMethodBase(): MapBasedJavaAnnotationOwner { + override val annotationsByFqNameHash by buildLazyValueForMap() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt new file mode 100644 index 00000000000..607e23aabb0 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt @@ -0,0 +1,21 @@ +interface ClassId + +interface JavaAnnotation { + val classId: ClassId? +} + +interface JavaAnnotationOwner { + val annotations: Collection +} + +interface MapBasedJavaAnnotationOwner : JavaAnnotationOwner { + val annotationsByFqNameHash: Map +} + +fun JavaAnnotationOwner.buildLazyValueForMap() = lazy { + annotations.associateBy { it.classId?.hashCode() } +} + +abstract class BinaryJavaMethodBase(): MapBasedJavaAnnotationOwner { + override val annotationsByFqNameHash by buildLazyValueForMap() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.txt b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.txt new file mode 100644 index 00000000000..1ac5e5e1a86 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.txt @@ -0,0 +1,40 @@ +package + +public fun JavaAnnotationOwner.buildLazyValueForMap(): kotlin.Lazy> + +public abstract class BinaryJavaMethodBase : MapBasedJavaAnnotationOwner { + public constructor BinaryJavaMethodBase() + public abstract override /*1*/ /*fake_override*/ val annotations: kotlin.collections.Collection + public open override /*1*/ val annotationsByFqNameHash: kotlin.collections.Map + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface ClassId { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface JavaAnnotation { + public abstract val classId: ClassId? + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface JavaAnnotationOwner { + public abstract val annotations: kotlin.collections.Collection + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface MapBasedJavaAnnotationOwner : JavaAnnotationOwner { + public abstract override /*1*/ /*fake_override*/ val annotations: kotlin.collections.Collection + public abstract val annotationsByFqNameHash: kotlin.collections.Map + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} 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 197f76038e4..c9b5822b670 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 @@ -30740,6 +30740,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/assignedInSynchronized.kt"); } + @Test + @TestMetadata("buildLazyValueForMap.kt") + public void testBuildLazyValueForMap() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt"); + } + @Test @TestMetadata("CallCompanionProtectedNonStatic.kt") public void testCallCompanionProtectedNonStatic() throws Exception { From 266432a48200075142c617cd97eb83508859c956 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Wed, 3 Feb 2021 22:11:18 -0800 Subject: [PATCH 007/153] FIR checker: fix condition for property type mismatch on override --- .../propertyTypeMismatchOnOverride.kt | 4 ++-- .../declaration/FirOverrideChecker.kt | 24 ++++++++++++------- .../diagnostics/tests/subtyping/kt3159.fir.kt | 9 ------- .../diagnostics/tests/subtyping/kt3159.kt | 1 + .../abstract-classes/p-2/neg/1.3.fir.kt | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/subtyping/kt3159.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt index 5c5c24fb52e..848b59e325a 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt @@ -3,7 +3,7 @@ open class A { } open class B : A { - override var test: Double = 20.0 + override var test: Double = 20.0 } class C() : A() { @@ -15,7 +15,7 @@ open class D() : B() { } class E(val value: T) : B() { - override var test: T = value + override var test: T = value } open class F(val value: T) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt index c059eb565ec..094a6426000 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt @@ -61,13 +61,13 @@ object FirOverrideChecker : FirRegularClassChecker() { private fun ConeKotlinType.substituteAllTypeParameters( overrideDeclaration: FirCallableMemberDeclaration<*>, - baseDeclarationSymbol: FirCallableSymbol<*>, + baseDeclaration: FirCallableDeclaration<*>, ): ConeKotlinType { if (overrideDeclaration.typeParameters.isEmpty()) { return this } - val parametersOwner = baseDeclarationSymbol.fir.safeAs() + val parametersOwner = baseDeclaration.safeAs() ?: return this val map = mutableMapOf() @@ -130,27 +130,35 @@ object FirOverrideChecker : FirRegularClassChecker() { } } + // See [OverrideResolver#isReturnTypeOkForOverride] private fun FirCallableMemberDeclaration<*>.checkReturnType( overriddenSymbols: List>, typeCheckerContext: AbstractTypeCheckerContext, context: CheckerContext, ): FirMemberDeclaration? { - val returnType = returnTypeRef.safeAs()?.type + val overridingReturnType = returnTypeRef.safeAs()?.type ?: return null // Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately. - if (returnType is ConeKotlinErrorType) { + if (overridingReturnType is ConeKotlinErrorType) { return null } val bounds = overriddenSymbols.map { context.returnTypeCalculator.tryCalculateReturnType(it.fir).coneType.upperBoundIfFlexible() } for (it in bounds.indices) { - val restriction = bounds[it] - .substituteAllTypeParameters(this, overriddenSymbols[it]) + val overriddenDeclaration = overriddenSymbols[it].fir - if (!AbstractTypeChecker.isSubtypeOf(typeCheckerContext, returnType, restriction)) { - return overriddenSymbols[it].fir.safeAs() + val overriddenReturnType = bounds[it].substituteAllTypeParameters(this, overriddenDeclaration) + + val isReturnTypeOkForOverride = + if (overriddenDeclaration is FirProperty && overriddenDeclaration.isVar) + AbstractTypeChecker.equalTypes(typeCheckerContext, overridingReturnType, overriddenReturnType) + else + AbstractTypeChecker.isSubtypeOf(typeCheckerContext, overridingReturnType, overriddenReturnType) + + if (!isReturnTypeOkForOverride) { + return overriddenDeclaration.safeAs() } } diff --git a/compiler/testData/diagnostics/tests/subtyping/kt3159.fir.kt b/compiler/testData/diagnostics/tests/subtyping/kt3159.fir.kt deleted file mode 100644 index 2d736b76b07..00000000000 --- a/compiler/testData/diagnostics/tests/subtyping/kt3159.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -interface Super { - var v: CharSequence - val v2: CharSequence -} - -class Sub: Super { - override var v: String = "fail" - override val v2: String = "ok" -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/subtyping/kt3159.kt b/compiler/testData/diagnostics/tests/subtyping/kt3159.kt index 11c335546d3..c4f6d9bca85 100644 --- a/compiler/testData/diagnostics/tests/subtyping/kt3159.kt +++ b/compiler/testData/diagnostics/tests/subtyping/kt3159.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface Super { var v: CharSequence val v2: CharSequence diff --git a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.3.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.3.fir.kt index 57af86eaa66..3f25c0fadc5 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/declarations/classifier-declaration/class-declaration/abstract-classes/p-2/neg/1.3.fir.kt @@ -18,7 +18,7 @@ class Case1 : Base() { override val a: Any? get() = TODO() - override var b: String + override var b: String get() = TODO() set(value) {} @@ -29,7 +29,7 @@ class Case1 : Base() { * TESTCASE NUMBER: 2 */ -class Case2(override val a: String, override var b: String) : Base() { +class Case2(override val a: String, override var b: String) : Base() { override fun foo(): CharSequence? { return "" } From 83e320167755258aea01cd34ff9c77a8bbff046b Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 4 Feb 2021 12:08:25 -0800 Subject: [PATCH 008/153] FIR DFA: correct exit node retrieval when a safe call is the last expression ^KT-44699 Fixed --- .../safeCallOnTypeAlias.fir.txt | 2 +- .../coercionToUnitWithEarlyReturn.fir.txt | 4 ++-- .../coercionToUnitWithEarlyReturn.kt | 2 +- .../dfa/cfg/ControlFlowGraphBuilder.kt | 10 ++++++-- .../buildLazyValueForMap.fir.kt | 23 ------------------- .../testsWithStdLib/buildLazyValueForMap.kt | 2 ++ 6 files changed, 14 insertions(+), 29 deletions(-) delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/safeCallOnTypeAlias.fir.txt b/compiler/fir/analysis-tests/testData/resolve/callResolution/safeCallOnTypeAlias.fir.txt index 23cb5301cc6..0e2211cd68c 100644 --- a/compiler/fir/analysis-tests/testData/resolve/callResolution/safeCallOnTypeAlias.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/safeCallOnTypeAlias.fir.txt @@ -1,7 +1,7 @@ FILE: safeCallOnTypeAlias.kt public final typealias MyTypeAlias = R|() -> kotlin/String?| public final fun foo(x: R|MyTypeAlias|): R|kotlin/Unit| { - R|/x|?.{ $subj$.R|kotlin/let| kotlin/String?|, R|kotlin/String|>( = let@fun (y: R|() -> kotlin/String?|): R|kotlin/String| { + R|/x|?.{ $subj$.R|kotlin/let| kotlin/String?|, R|kotlin/String?|>( = let@fun (y: R|() -> kotlin/String?|): R|kotlin/String?| { ^ R|/y|.R|SubstitutionOverride|()?.{ $subj$.R|kotlin/let|( = let@fun (result: R|kotlin/String|): R|kotlin/String| { ^ R|/bar|(R|/result|) } diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.fir.txt b/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.fir.txt index e04a089fcf3..a819ba09632 100644 --- a/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.fir.txt @@ -11,7 +11,7 @@ FILE: coercionToUnitWithEarlyReturn.kt public final fun foo(x: R|() -> kotlin/Unit|): R|kotlin/Unit| { } public final fun main(x: R|A?|): R|kotlin/Unit| { - lval lambda: R|() -> kotlin/Unit| = l@fun (): R|kotlin/Unit| { + lval lambda: R|() -> kotlin/Unit?| = l@fun (): R|kotlin/Unit?| { when () { ==(R|/x|?.{ $subj$.R|kotlin/Any.hashCode|() }, Int(0)) -> { ^@l Unit @@ -21,5 +21,5 @@ FILE: coercionToUnitWithEarlyReturn.kt ^ R|/x|?.{ $subj$.R|/A.unit|() } } - R|/foo|(R|/lambda|) + #(R|/lambda|) } diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.kt b/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.kt index 1739ea41199..575ef2a0fe7 100644 --- a/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.kt +++ b/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.kt @@ -15,5 +15,5 @@ fun main(x: A?) { } // lambda has a type (() -> Unit?) - foo(lambda) + foo(lambda) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 3a3e2ac5653..8bb8403593d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -133,7 +133,6 @@ class ControlFlowGraphBuilder { fun CFGNode<*>.extractArgument(): FirElement? = when (this) { is FunctionEnterNode, is TryMainBlockEnterNode, is CatchClauseEnterNode -> null - is ExitSafeCallNode -> lastPreviousNode.extractArgument() is StubNode, is BlockExitNode -> firstPreviousNode.extractArgument() else -> fir.extractArgument() } @@ -1090,8 +1089,9 @@ class ControlFlowGraphBuilder { * lastNode -> exitNode * instead of * lastNode -> enterNode -> exitNode - * because of we need to fork flow on `enterNode`, so `exitNode` + * because we need to fork flow before `enterNode`, so `exitNode` * will have unchanged flow from `lastNode` + * which corresponds to a path with nullable receiver. */ val lastNode = lastNodes.pop() val enterNode = createEnterSafeCallNode(safeCall) @@ -1104,6 +1104,12 @@ class ControlFlowGraphBuilder { } fun exitSafeCall(): ExitSafeCallNode { + // There will be two paths towards this exit safe call node: + // one from the node prior to the enclosing safe call, and + // the other from the selector part in the enclosing safe call. + // Note that *neither* points to the safe call directly. + // So, when it comes to the real exit of the enclosing block/function, + // the safe call bound to this exit safe call node should be retrieved. return exitSafeCallNodes.pop().also { addNewSimpleNode(it) it.updateDeadStatus() diff --git a/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.fir.kt deleted file mode 100644 index d2698163573..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.fir.kt +++ /dev/null @@ -1,23 +0,0 @@ -// !WITH_NEW_INFERENCE - -interface ClassId - -interface JavaAnnotation { - val classId: ClassId? -} - -interface JavaAnnotationOwner { - val annotations: Collection -} - -interface MapBasedJavaAnnotationOwner : JavaAnnotationOwner { - val annotationsByFqNameHash: Map -} - -fun JavaAnnotationOwner.buildLazyValueForMap() = lazy { - annotations.associateBy { it.classId?.hashCode() } -} - -abstract class BinaryJavaMethodBase(): MapBasedJavaAnnotationOwner { - override val annotationsByFqNameHash by buildLazyValueForMap() -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt index 607e23aabb0..be566e49c07 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/buildLazyValueForMap.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL + interface ClassId interface JavaAnnotation { From 37a702b96276e5f797e0f086fa3b18db912b9e6a Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 5 Feb 2021 10:38:45 -0800 Subject: [PATCH 009/153] FIR: coerce to Unit when a lambda has early returns ^KT-39075 Fixed --- .../coercionToUnitWithEarlyReturn.fir.txt | 4 +-- .../coercionToUnitWithEarlyReturn.kt | 3 +- .../FirDeclarationsResolveTransformer.kt | 30 ++++++++++++++----- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.fir.txt b/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.fir.txt index a819ba09632..e04a089fcf3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.fir.txt @@ -11,7 +11,7 @@ FILE: coercionToUnitWithEarlyReturn.kt public final fun foo(x: R|() -> kotlin/Unit|): R|kotlin/Unit| { } public final fun main(x: R|A?|): R|kotlin/Unit| { - lval lambda: R|() -> kotlin/Unit?| = l@fun (): R|kotlin/Unit?| { + lval lambda: R|() -> kotlin/Unit| = l@fun (): R|kotlin/Unit| { when () { ==(R|/x|?.{ $subj$.R|kotlin/Any.hashCode|() }, Int(0)) -> { ^@l Unit @@ -21,5 +21,5 @@ FILE: coercionToUnitWithEarlyReturn.kt ^ R|/x|?.{ $subj$.R|/A.unit|() } } - #(R|/lambda|) + R|/foo|(R|/lambda|) } diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.kt b/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.kt index 575ef2a0fe7..17e399120e2 100644 --- a/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.kt +++ b/compiler/fir/analysis-tests/testData/resolve/inference/coercionToUnitWithEarlyReturn.kt @@ -14,6 +14,5 @@ fun main(x: A?) { x?.unit() } - // lambda has a type (() -> Unit?) - foo(lambda) + foo(lambda) } 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 6fc9b4397a9..826950c76fc 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 @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult @@ -780,13 +781,28 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor dataFlowAnalyzer, ) lambda.transformSingle(writer, expectedTypeRef.coneTypeSafe()?.toExpectedType()) - val returnTypes = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(lambda) - .mapNotNull { (it as? FirExpression)?.resultType?.coneType } - lambda.replaceReturnTypeRef( - lambda.returnTypeRef.resolvedTypeFromPrototype( - inferenceComponents.ctx.commonSuperTypeOrNull(returnTypes) ?: session.builtinTypes.unitType.type - ) - ) + + val returnStatements = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(lambda) + val returnExpressionsExceptLast = + if (returnStatements.size > 1) + returnStatements - lambda.body?.statements?.lastOrNull() + else + returnStatements + val implicitReturns = returnExpressionsExceptLast.filter { + (it as? FirExpression)?.typeRef is FirImplicitUnitTypeRef + } + val returnType = + if (implicitReturns.isNotEmpty()) { + // i.e., early return, e.g., l@{ ... return@l ... } + // Note that the last statement will be coerced to Unit if needed. + session.builtinTypes.unitType.type + } else { + // Otherwise, compute the common super type of all possible return expressions + inferenceComponents.ctx.commonSuperTypeOrNull( + returnStatements.mapNotNull { (it as? FirExpression)?.resultType?.coneType } + ) ?: session.builtinTypes.unitType.type + } + lambda.replaceReturnTypeRef(lambda.returnTypeRef.resolvedTypeFromPrototype(returnType)) lambda.replaceTypeRef( lambda.constructFunctionalTypeRef( isSuspend = expectedTypeRef.coneTypeSafe()?.isSuspendFunctionType(session) == true From a9322a01ce5a05827215b977903d8ca74b6d6717 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Sat, 6 Feb 2021 22:59:37 -0800 Subject: [PATCH 010/153] FIR checker: avoid redundant casting to resolved type ref --- .../fir/analysis/checkers/FirHelpers.kt | 15 ++++---------- .../FirConflictingProjectionChecker.kt | 2 ++ .../declaration/FirOverrideChecker.kt | 3 +-- .../declaration/FirSealedSupertypeChecker.kt | 19 +++++------------- .../expression/FirCatchParameterChecker.kt | 1 + ...upertypeExtendedByOtherSupertypeChecker.kt | 5 ++--- .../FirSealedClassConstructorCallChecker.kt | 6 +++--- .../FirUpperBoundViolatedChecker.kt | 20 +++++++++---------- .../extended/UselessCallOnNotNullChecker.kt | 5 ++--- 9 files changed, 30 insertions(+), 46 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index ab254cab222..4de8ec9b974 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -22,23 +22,19 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope -import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.typeCheckerContext import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtModifierList -import org.jetbrains.kotlin.psi.KtObjectLiteralExpression import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -132,7 +128,7 @@ fun ConeKotlinType.toRegularClass(session: FirSession): FirRegularClass? { * or null of something goes wrong. */ fun FirTypeRef.toRegularClass(session: FirSession): FirRegularClass? { - return safeAs()?.type?.toRegularClass(session) + return coneType.toRegularClass(session) } /** @@ -289,18 +285,15 @@ private fun FirDeclaration.hasBody(): Boolean = when (this) { * or null if couldn't find any. */ fun FirClass<*>.findNonInterfaceSupertype(context: CheckerContext): FirTypeRef? { - for (it in superTypeRefs) { - val lookupTag = it.safeAs() - ?.type.safeAs() - ?.lookupTag - ?: continue + for (superTypeRef in superTypeRefs) { + val lookupTag = superTypeRef.coneType.safeAs()?.lookupTag ?: continue val fir = lookupTag.toSymbol(context.session) ?.fir.safeAs>() ?: continue if (fir.classKind != ClassKind.INTERFACE) { - return it + return superTypeRef } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictingProjectionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictingProjectionChecker.kt index 577a93cd63e..b82cb04fc20 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictingProjectionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictingProjectionChecker.kt @@ -44,6 +44,8 @@ object FirConflictingProjectionChecker : FirBasicDeclarationChecker() { } private fun checkTypeRef(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) { + // TODO: remaining implicit types should be resolved as an error type, along with proper error kind, + // e.g., type mismatch, can't infer parameter type, syntax error, etc. val declaration = typeRef.safeAs() ?.coneTypeSafe() ?.lookupTag diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt index 094a6426000..8302f1adc3a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt @@ -136,8 +136,7 @@ object FirOverrideChecker : FirRegularClassChecker() { typeCheckerContext: AbstractTypeCheckerContext, context: CheckerContext, ): FirMemberDeclaration? { - val overridingReturnType = returnTypeRef.safeAs()?.type - ?: return null + val overridingReturnType = returnTypeRef.coneType // Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately. if (overridingReturnType is ConeKotlinErrorType) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt index 73151cf1fc2..91d1c9b3e64 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt @@ -12,8 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.firSymbolProvider -import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.classId +import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.utils.addToStdlib.safeAs object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { @@ -41,10 +41,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { private fun checkTopLevelDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) { for (it in declaration.superTypeRefs) { - val classId = it.safeAs() - ?.type.safeAs() - ?.lookupTag?.classId - ?: continue + val classId = it.coneType.classId ?: continue if (classId.isLocal) { continue @@ -63,10 +60,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { private fun checkLocalDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) { for (it in declaration.superTypeRefs) { - val classId = it.safeAs() - ?.type.safeAs() - ?.lookupTag?.classId - ?: continue + val classId = it.coneType.classId ?: continue if (classId.isLocal) { continue @@ -85,10 +79,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { private fun checkInnerDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) { for (it in declaration.superTypeRefs) { - val classId = it.safeAs() - ?.type.safeAs() - ?.lookupTag?.classId - ?: continue + val classId = it.coneType.classId ?: continue if (classId.isLocal) { continue diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt index b4899e2394b..79970e5eda7 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt @@ -25,6 +25,7 @@ object FirCatchParameterChecker : FirTryExpressionChecker() { } val typeRef = catchParameter.returnTypeRef + // TODO: remaining implicit types should be resolved as an error type, along with proper error kind, most likely syntax error. if (typeRef !is FirResolvedTypeRef) return val coneType = typeRef.type diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirQualifiedSupertypeExtendedByOtherSupertypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirQualifiedSupertypeExtendedByOtherSupertypeChecker.kt index 6dd050ad8d1..5a684a64e64 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirQualifiedSupertypeExtendedByOtherSupertypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirQualifiedSupertypeExtendedByOtherSupertypeChecker.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.utils.addToStdlib.safeAs object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccessChecker() { @@ -26,8 +25,8 @@ object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccess ?.takeIf { it.hadExplicitTypeInSource() } ?: return - val explicitType = superReference.superTypeRef.safeAs() - ?.firClassLike(context.session) + val explicitType = superReference.superTypeRef + .firClassLike(context.session) ?.followAllAlias(context.session).safeAs>() ?: return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSealedClassConstructorCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSealedClassConstructorCallChecker.kt index 3eaf87d9cd9..600d4415e4d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSealedClassConstructorCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSealedClassConstructorCallChecker.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.utils.addToStdlib.safeAs object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() { @@ -26,8 +26,8 @@ object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() { ?.fir.safeAs() ?: return - val typeFir = constructorFir.returnTypeRef.safeAs() - ?.type.safeAs() + val typeFir = constructorFir.returnTypeRef.coneType + .safeAs() ?.lookupTag?.toSymbol(context.session) ?.fir as? FirRegularClass ?: return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedChecker.kt index 1b326fa99da..d469fdeaf28 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedChecker.kt @@ -43,11 +43,11 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() { return } - val parameterPairs = mutableMapOf() + val parameterPairs = mutableMapOf() for (it in 0 until count) { expression.typeArguments[it].safeAs() - ?.typeRef.safeAs() + ?.typeRef ?.let { that -> if (that !is FirErrorTypeRef) { parameterPairs[calleeFir.typeParameters[it].symbol] = that @@ -60,7 +60,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() { // we substitute actual values to the // type parameters from the declaration val substitutor = substitutorByMap( - parameterPairs.mapValues { it.value.type } + parameterPairs.mapValues { it.value.coneType } ) val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext( @@ -74,14 +74,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() { return@forEach } - if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) { - reporter.reportOn(actual.source, proto, actual.type, context) + if (!satisfiesBounds(proto, actual.coneType, substitutor, typeCheckerContext)) { + reporter.reportOn(actual.source, proto, actual.coneType, context) return } // we must analyze nested things like // S, T>() - actual.type.safeAs()?.let { + actual.coneType.safeAs()?.let { val errorOccurred = analyzeTypeParameters(it, context, reporter, typeCheckerContext, actual.source) if (errorOccurred) { @@ -125,8 +125,8 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() { val actualConstructor = functionCall.calleeReference.safeAs() ?.resolvedSymbol.safeAs() ?.fir.safeAs() - ?.returnTypeRef.safeAs() - ?.type.safeAs() + ?.returnTypeRef?.coneType + ?.safeAs() ?: return val count = min(protoConstructor.typeParameters.size, actualConstructor.typeArguments.size) @@ -158,7 +158,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() { constructorsParameterPairs.forEach { (proto, actual) -> // just in case var intersection = typeCheckerContext.intersectTypes( - proto.fir.bounds.filterIsInstance().map { it.type } + proto.fir.bounds.map { it.coneType } ).safeAs() ?: return@forEach intersection = declarationSiteSubstitutor.substituteOrSelf(intersection) @@ -245,7 +245,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() { typeCheckerContext: AbstractTypeCheckerContext ): Boolean { var intersection = typeCheckerContext.intersectTypes( - prototypeSymbol.fir.bounds.filterIsInstance().map { it.type } + prototypeSymbol.fir.bounds.map { it.coneType } ).safeAs() ?: return true intersection = substitutor.substituteOrSelf(intersection) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UselessCallOnNotNullChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UselessCallOnNotNullChecker.kt index 8faa654deff..94b681f2934 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UselessCallOnNotNullChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UselessCallOnNotNullChecker.kt @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.types.ConeNullability -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.fir.types.coneType @@ -37,9 +36,9 @@ object UselessCallOnNotNullChecker : FirQualifiedAccessChecker() { ((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol)?.callableId private fun FirExpression.getPackage() = - (typeRef as? FirResolvedTypeRef)?.coneType?.classId?.packageFqName.toString() + typeRef.coneType.classId?.packageFqName.toString() - private fun FirExpression.getNullability() = (typeRef as FirResolvedTypeRef).type.nullability + private fun FirExpression.getNullability() = typeRef.coneType.nullability private val triggerOn = setOf( From 6c051b2be4d0e3bd18e74ce8bdde5e99a46df0d2 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Wed, 3 Feb 2021 19:24:26 +0300 Subject: [PATCH 011/153] [JS IR] Override method are not exported [JS IR] Add test with jsexport overrides not js export method with stable name ^KT-44616 fixed --- .../backend/js/export/ExportModelGenerator.kt | 26 +++++++++--- .../semantics/IrBoxJsES6TestGenerated.java | 10 +++++ .../ir/semantics/IrBoxJsTestGenerated.java | 10 +++++ .../js/test/semantics/BoxJsTestGenerated.java | 10 +++++ ...rriddenExternalMethodWithSameNameMethod.kt | 38 +++++++++++++++++ ...nExternalMethodWithSameStableNameMethod.kt | 41 +++++++++++++++++++ 6 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt create mode 100644 js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt index abbe7072fc8..b4f51ffc777 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt @@ -8,10 +8,12 @@ package org.jetbrains.kotlin.ir.backend.js.export import org.jetbrains.kotlin.backend.common.ir.isExpect import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.DescriptorVisibilities -import org.jetbrains.kotlin.ir.backend.js.* -import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.* +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin +import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.ES6_INIT_BOX_PARAMETER +import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.ES6_RESULT_TYPE_PARAMETER import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName import org.jetbrains.kotlin.ir.backend.js.utils.isJsExport import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName @@ -80,7 +82,7 @@ class ExportModelGenerator(val context: JsIrBackendContext) { private fun exportConstructor(constructor: IrConstructor): ExportedDeclaration? { if (!constructor.isPrimary) return null val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) + - constructor.valueParameters.filterNot { it.origin === ES6_RESULT_TYPE_PARAMETER || it.origin === ES6_INIT_BOX_PARAMETER } + constructor.valueParameters.filterNot { it.origin === ES6_RESULT_TYPE_PARAMETER || it.origin === ES6_INIT_BOX_PARAMETER } return ExportedConstructor(allValueParameters.map { exportParameter(it) }) } @@ -192,7 +194,7 @@ class ExportModelGenerator(val context: JsIrBackendContext) { ?.let { exportType(it).takeIf { it !is ExportedType.ErrorType } } val superInterfaces = klass.superTypes - .filter {it.classifierOrFail.isInterface } + .filter { it.classifierOrFail.isInterface } .map { exportType(it) } .filter { it !is ExportedType.ErrorType } @@ -398,6 +400,16 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont if (context?.additionalExportedDeclarations?.contains(declaration) == true) return true + if (declaration is IrSimpleFunction) { + val overriddenNonEmpty = declaration + .overriddenSymbols + .isNotEmpty() + + if (overriddenNonEmpty) { + return declaration.isOverriddenExported(context) + } + } + if (declaration.isJsExport()) return true @@ -408,6 +420,10 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont } } +private fun IrSimpleFunction.isOverriddenExported(context: JsIrBackendContext?): Boolean = + overriddenSymbols + .any { shouldDeclarationBeExported(it.owner, context) } + fun IrDeclaration.isExported(context: JsIrBackendContext?): Boolean { val candidate = getExportCandidate(this) ?: return false return shouldDeclarationBeExported(candidate, context) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java index a2520f7fae2..6bab51ea5c6 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java @@ -1632,6 +1632,16 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") + public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + @TestMetadata("overridenMethod.kt") public void testOverridenMethod() throws Exception { runTest("js/js.translator/testData/box/export/overridenMethod.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index 6a722ac2d4b..11901a52caa 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -1632,6 +1632,16 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") + public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + @TestMetadata("overridenMethod.kt") public void testOverridenMethod() throws Exception { runTest("js/js.translator/testData/box/export/overridenMethod.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 4bffcc65168..da503f4f0b0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -1637,6 +1637,16 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") + public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + @TestMetadata("overridenMethod.kt") public void testOverridenMethod() throws Exception { runTest("js/js.translator/testData/box/export/overridenMethod.kt"); diff --git a/js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt b/js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt new file mode 100644 index 00000000000..bc9a6222260 --- /dev/null +++ b/js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt @@ -0,0 +1,38 @@ +// IGNORE_BACKEND: JS +// RUN_PLAIN_BOX_FUNCTION +// INFER_MAIN_MODULE + +// MODULE: overriden-external-method-with-same-name-method +// FILE: lib.kt +external abstract class Foo { + abstract fun o(): String +} + +abstract class Bar : Foo() { + abstract fun String.o(): String + + override fun o(): String { + return "O".o() + } +} + +@JsExport +class Baz : Bar() { + override fun String.o(): String { + return this + } +} + +// FILE: test.js +function Foo() {} +Foo.prototype.k = function() { + return "K" +} + +function box() { + return test(new this["overriden-external-method-with-same-name-method"].Baz()); +} + +function test(foo) { + return foo.o() + foo.k() +} \ No newline at end of file diff --git a/js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt b/js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt new file mode 100644 index 00000000000..3bc6dcae649 --- /dev/null +++ b/js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt @@ -0,0 +1,41 @@ +// IGNORE_BACKEND: JS +// RUN_PLAIN_BOX_FUNCTION +// INFER_MAIN_MODULE + +// MODULE: overriden-external-method-with-same-stable-name-method +// FILE: lib.kt +external abstract class Foo { + abstract fun o(): String +} + +abstract class Bar : Foo() { + @JsName("oStable") + abstract fun String.o(): String + + override fun o(): String { + return "O".o() + } +} + +@JsExport +class Baz : Bar() { + override fun String.o(): String { + return this + } +} + +// FILE: test.js +function Foo() {} +Foo.prototype.k = function() { + return "K" +} + +function box() { + return test(new this["overriden-external-method-with-same-stable-name-method"].Baz()); +} + +function test(foo) { + const oStable = foo.oStable("OK") + if (oStable !== "OK") return "false: " + oStable + return foo.o() + foo.k() +} \ No newline at end of file From 7b4624aac4647e1e83151f659bc9c421eb1a4d4f Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Thu, 4 Feb 2021 13:32:11 +0300 Subject: [PATCH 012/153] [JS IR] Add exported method into exportNestedClass.kt ^KT-44616 fixed --- js/js.translator/testData/box/export/exportNestedClass.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/js.translator/testData/box/export/exportNestedClass.kt b/js/js.translator/testData/box/export/exportNestedClass.kt index ac724223f75..5bb3a61cecc 100644 --- a/js/js.translator/testData/box/export/exportNestedClass.kt +++ b/js/js.translator/testData/box/export/exportNestedClass.kt @@ -16,10 +16,14 @@ class B { override fun foo(k: String): String { return "O" + k } + + fun bar(k: String): String { + return foo(k) + } } } // FILE: test.js function box() { - return new this["export-nested-class"].B.Foo().foo("K"); + return new this["export-nested-class"].B.Foo().bar("K"); } \ No newline at end of file From 76b124a9c06fbdf8128b105def9bca1aeeb9cea8 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Thu, 4 Feb 2021 16:51:28 +0300 Subject: [PATCH 013/153] [JS IR] Method of any is exported ^KT-44616 fixed --- .../kotlin/ir/backend/js/export/ExportModelGenerator.kt | 4 +++- .../src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt index b4f51ffc777..114c32d9826 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.ir.backend.js.export import org.jetbrains.kotlin.backend.common.ir.isExpect +import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -406,7 +407,8 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont .isNotEmpty() if (overriddenNonEmpty) { - return declaration.isOverriddenExported(context) + return declaration.isOverriddenExported(context) || + declaration.isMethodOfAny() // Handle names for special functions } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt index 2f597d3dddc..1cc9a52545f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt @@ -19,7 +19,6 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.isNullableAny import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.ir.util.isTopLevelDeclaration -import org.jetbrains.kotlin.ir.util.parentClassOrNull import org.jetbrains.kotlin.name.Name fun TODO(element: IrElement): Nothing = TODO(element::class.java.simpleName + " is not supported yet here") From 19bffc694be6d83d4e0c32a3754d7bcb3f1095e8 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Mon, 8 Feb 2021 11:48:50 +0300 Subject: [PATCH 014/153] [JS IR] Add test with chain export--not-export--export ^KT-44616 fixed --- .../semantics/IrBoxJsES6TestGenerated.java | 5 +++ .../ir/semantics/IrBoxJsTestGenerated.java | 5 +++ .../js/test/semantics/BoxJsTestGenerated.java | 5 +++ .../overriddenChainNonExportIntermediate.kt | 38 +++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 js/js.translator/testData/box/export/overriddenChainNonExportIntermediate.kt diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java index 6bab51ea5c6..2431469a3cd 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java @@ -1632,6 +1632,11 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenChainNonExportIntermediate.kt") + public void testOverriddenChainNonExportIntermediate() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenChainNonExportIntermediate.kt"); + } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index 11901a52caa..902c771bee4 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -1632,6 +1632,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenChainNonExportIntermediate.kt") + public void testOverriddenChainNonExportIntermediate() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenChainNonExportIntermediate.kt"); + } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index da503f4f0b0..74d0097f158 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -1637,6 +1637,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenChainNonExportIntermediate.kt") + public void testOverriddenChainNonExportIntermediate() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenChainNonExportIntermediate.kt"); + } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); diff --git a/js/js.translator/testData/box/export/overriddenChainNonExportIntermediate.kt b/js/js.translator/testData/box/export/overriddenChainNonExportIntermediate.kt new file mode 100644 index 00000000000..b04e9fc2b5e --- /dev/null +++ b/js/js.translator/testData/box/export/overriddenChainNonExportIntermediate.kt @@ -0,0 +1,38 @@ +// IGNORE_BACKEND: JS +// RUN_PLAIN_BOX_FUNCTION +// INFER_MAIN_MODULE + +// MODULE: overriden-chain-non-export-intermediate +// FILE: lib.kt +@JsExport +abstract class A { + abstract fun foo(): String + + abstract fun bar(): String +} + +abstract class B : A() { + abstract fun baz(): String + + override fun foo(): String = "foo" +} + +@JsExport +class C : B() { + override fun bar(): String = "bar" + override fun baz(): String = "baz" + + fun bay(): String = "bay" +} + +// FILE: test.js + +function box() { + return test(new this["overriden-chain-non-export-intermediate"].C()); +} + +function test(c) { + if (c.foo() === "foo" && c.bar() === "bar" && c.bay() == "bay") return "OK" + + return "fail" +} \ No newline at end of file From 694d69fbfa7bc28a5c03e4051556490db1221015 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 4 Feb 2021 15:36:05 +0300 Subject: [PATCH 015/153] FIR2IR: select return target inside accessor properly --- .../fir/backend/Fir2IrConversionScope.kt | 15 ++- .../kotlin/fir/backend/Fir2IrVisitor.kt | 2 +- .../generators/FakeOverrideGenerator.kt | 2 +- .../runners/ir/Fir2IrTextTestGenerated.java | 6 + .../fromInterfaceDefaultGetter.kt | 1 - .../nonLocalReturns/propertyAccessors.kt | 1 - .../firProblems/SafeLetWithReturn.fir.kt.txt | 52 +++++++++ .../firProblems/SafeLetWithReturn.fir.txt | 105 ++++++++++++++++++ .../irText/firProblems/SafeLetWithReturn.kt | 25 +++++ .../firProblems/SafeLetWithReturn.kt.txt | 52 +++++++++ .../irText/firProblems/SafeLetWithReturn.txt | 105 ++++++++++++++++++ .../test/runners/ir/IrTextTestGenerated.java | 6 + 12 files changed, 365 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/ir/irText/firProblems/SafeLetWithReturn.fir.kt.txt create mode 100644 compiler/testData/ir/irText/firProblems/SafeLetWithReturn.fir.txt create mode 100644 compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt create mode 100644 compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt.txt create mode 100644 compiler/testData/ir/irText/firProblems/SafeLetWithReturn.txt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConversionScope.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConversionScope.kt index 06c56ba98ec..b679005a6d2 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConversionScope.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConversionScope.kt @@ -59,10 +59,10 @@ class Fir2IrConversionScope { return function } - private val propertyStack = mutableListOf() + private val propertyStack = mutableListOf>() - fun withProperty(property: IrProperty, f: IrProperty.() -> Unit): IrProperty { - propertyStack += property + fun withProperty(property: IrProperty, firProperty: FirProperty? = null, f: IrProperty.() -> Unit): IrProperty { + propertyStack += (property to firProperty) property.f() propertyStack.removeAt(propertyStack.size - 1) return property @@ -99,6 +99,15 @@ class Fir2IrConversionScope { val irTarget = (firTarget as? FirFunction)?.let { when (it) { is FirConstructor -> declarationStorage.getCachedIrConstructor(it) + is FirPropertyAccessor -> { + for ((property, firProperty) in propertyStack.asReversed()) { + if (firProperty?.getter === firTarget) { + return@let property.getter + } else if (firProperty?.setter === firTarget) { + return@let property.setter + } + } + } else -> declarationStorage.getCachedIrFunction(it) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 8b418059d09..b6f40c35c39 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -269,7 +269,7 @@ class Fir2IrVisitor( override fun visitProperty(property: FirProperty, data: Any?): IrElement { if (property.isLocal) return visitLocalVariable(property) val irProperty = declarationStorage.getCachedIrProperty(property)!! - return conversionScope.withProperty(irProperty) { + return conversionScope.withProperty(irProperty, property) { memberGenerator.convertPropertyContent(irProperty, property, containingClass = conversionScope.containerFirClass()) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt index f3c2639dfce..18602971925 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt @@ -41,7 +41,7 @@ class FakeOverrideGenerator( } private fun IrProperty.withProperty(f: IrProperty.() -> Unit): IrProperty { - return conversionScope.withProperty(this, f) + return conversionScope.withProperty(this, firProperty = null, f) } private fun FirCallableMemberDeclaration<*>.allowsToHaveFakeOverrideIn(klass: FirClass<*>): Boolean { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java index 03704c65aac..7bd135d100f 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java @@ -2182,6 +2182,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/firProblems/recursiveCapturedTypeInPropertyReference.kt"); } + @Test + @TestMetadata("SafeLetWithReturn.kt") + public void testSafeLetWithReturn() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt"); + } + @Test @TestMetadata("SameJavaFieldReferences.kt") public void testSameJavaFieldReferences() throws Exception { diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt index 3931a5b00e5..8f2b2734c17 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt index c7229da93c3..275024ae34f 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // FILE: 1.kt package test diff --git a/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.fir.kt.txt b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.fir.kt.txt new file mode 100644 index 00000000000..3bf28334e98 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.fir.kt.txt @@ -0,0 +1,52 @@ +fun foo(s: String?): String { + { // BLOCK + val tmp0_safe_receiver: String? = s + when { + EQEQ(arg0 = tmp0_safe_receiver, arg1 = null) -> null + else -> tmp0_safe_receiver.let(block = local fun (it: String): Nothing { + return it + } +) + } + } /*~> Unit */ + return "" +} + +fun bar(s: String?, t: String?): String { + { // BLOCK + val tmp1_safe_receiver: String? = s + when { + EQEQ(arg0 = tmp1_safe_receiver, arg1 = null) -> null + else -> tmp1_safe_receiver.let(block = local fun (it: String): Nothing? { + return { // BLOCK + val tmp2_safe_receiver: String? = t + when { + EQEQ(arg0 = tmp2_safe_receiver, arg1 = null) -> null + else -> tmp2_safe_receiver.let(block = local fun (it: String): Nothing { + return it + } +) + } + } + } +) + } + } /*~> Unit */ + return "" +} + +val String?.baz: String + get(): String { + { // BLOCK + val tmp3_safe_receiver: String? = + when { + EQEQ(arg0 = tmp3_safe_receiver, arg1 = null) -> null + else -> tmp3_safe_receiver.let(block = local fun (it: String): Nothing { + return it + } +) + } + } /*~> Unit */ + return "" + } + diff --git a/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.fir.txt b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.fir.txt new file mode 100644 index 00000000000..4a50937c199 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.fir.txt @@ -0,0 +1,105 @@ +FILE fqName: fileName:/SafeLetWithReturn.kt + FUN name:foo visibility:public modality:FINAL <> (s:kotlin.String?) returnType:kotlin.String + VALUE_PARAMETER name:s index:0 type:kotlin.String? + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Nothing? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.String? [val] + GET_VAR 's: kotlin.String? declared in .foo' type=kotlin.String? origin=null + WHEN type=kotlin.Nothing? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_0: kotlin.String? [val] declared in .foo' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.StandardKt.let [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null + : kotlin.String + : kotlin.Nothing + $receiver: GET_VAR 'val tmp_0: kotlin.String? [val] declared in .foo' type=kotlin.String? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.Nothing + VALUE_PARAMETER name:it index:0 type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun foo (s: kotlin.String?): kotlin.String declared in ' + GET_VAR 'it: kotlin.String declared in .foo.' type=kotlin.String origin=null + RETURN type=kotlin.Nothing from='public final fun foo (s: kotlin.String?): kotlin.String declared in ' + CONST String type=kotlin.String value="" + FUN name:bar visibility:public modality:FINAL <> (s:kotlin.String?, t:kotlin.String?) returnType:kotlin.String + VALUE_PARAMETER name:s index:0 type:kotlin.String? + VALUE_PARAMETER name:t index:1 type:kotlin.String? + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Nothing? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.String? [val] + GET_VAR 's: kotlin.String? declared in .bar' type=kotlin.String? origin=null + WHEN type=kotlin.Nothing? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_1: kotlin.String? [val] declared in .bar' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.StandardKt.let [inline] declared in kotlin.StandardKt' type=kotlin.Nothing? origin=null + : kotlin.String + : kotlin.Nothing? + $receiver: GET_VAR 'val tmp_1: kotlin.String? [val] declared in .bar' type=kotlin.String? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.Nothing? + VALUE_PARAMETER name:it index:0 type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.String): kotlin.Nothing? declared in .bar' + BLOCK type=kotlin.Nothing? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.String? [val] + GET_VAR 't: kotlin.String? declared in .bar' type=kotlin.String? origin=null + WHEN type=kotlin.Nothing? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_2: kotlin.String? [val] declared in .bar.' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.StandardKt.let [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null + : kotlin.String + : kotlin.Nothing + $receiver: GET_VAR 'val tmp_2: kotlin.String? [val] declared in .bar.' type=kotlin.String? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.Nothing + VALUE_PARAMETER name:it index:0 type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun bar (s: kotlin.String?, t: kotlin.String?): kotlin.String declared in ' + GET_VAR 'it: kotlin.String declared in .bar..' type=kotlin.String origin=null + RETURN type=kotlin.Nothing from='public final fun bar (s: kotlin.String?, t: kotlin.String?): kotlin.String declared in ' + CONST String type=kotlin.String value="" + PROPERTY name:baz visibility:public modality:FINAL [val] + FUN name: visibility:public modality:FINAL <> ($receiver:kotlin.String?) returnType:kotlin.String + correspondingProperty: PROPERTY name:baz visibility:public modality:FINAL [val] + $receiver: VALUE_PARAMETER name: type:kotlin.String? + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Nothing? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.String? [val] + GET_VAR ': kotlin.String? declared in .' type=kotlin.String? origin=null + WHEN type=kotlin.Nothing? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_3: kotlin.String? [val] declared in .' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.StandardKt.let [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null + : kotlin.String + : kotlin.Nothing + $receiver: GET_VAR 'val tmp_3: kotlin.String? [val] declared in .' type=kotlin.String? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.Nothing + VALUE_PARAMETER name:it index:0 type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in ' + GET_VAR 'it: kotlin.String declared in ..' type=kotlin.String origin=null + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in ' + CONST String type=kotlin.String value="" diff --git a/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt new file mode 100644 index 00000000000..a1944d97ff4 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt @@ -0,0 +1,25 @@ +// WITH_RUNTIME + +fun foo(s: String?): String { + s?.let { it -> + return it + } + return "" +} + +fun bar(s: String?, t: String?): String { + s?.let { + t?.let { + return it + } + } + return "" +} + +val String?.baz: String + get() { + this?.let { + return it + } + return "" + } \ No newline at end of file diff --git a/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt.txt b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt.txt new file mode 100644 index 00000000000..aca6153a0e8 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt.txt @@ -0,0 +1,52 @@ +fun foo(s: String?): String { + { // BLOCK + val tmp0_safe_receiver: String? = s + when { + EQEQ(arg0 = tmp0_safe_receiver, arg1 = null) -> null + else -> tmp0_safe_receiver.let(block = local fun (it: String): Nothing { + return it + } +) + } + } /*~> Unit */ + return "" +} + +fun bar(s: String?, t: String?): String { + { // BLOCK + val tmp0_safe_receiver: String? = s + when { + EQEQ(arg0 = tmp0_safe_receiver, arg1 = null) -> null + else -> tmp0_safe_receiver.let(block = local fun (it: String): Nothing? { + { // BLOCK + val tmp0_safe_receiver: String? = t + when { + EQEQ(arg0 = tmp0_safe_receiver, arg1 = null) -> null + else -> tmp0_safe_receiver.let(block = local fun (it: String): Nothing { + return it + } +) + } + } /*~> Unit */ + } +) + } + } /*~> Unit */ + return "" +} + +val String?.baz: String + get(): String { + { // BLOCK + val tmp0_safe_receiver: String? = + when { + EQEQ(arg0 = tmp0_safe_receiver, arg1 = null) -> null + else -> tmp0_safe_receiver.let(block = local fun (it: String): Nothing { + return it + } +) + } + } /*~> Unit */ + return "" + } + diff --git a/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.txt b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.txt new file mode 100644 index 00000000000..78487630cb9 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/SafeLetWithReturn.txt @@ -0,0 +1,105 @@ +FILE fqName: fileName:/SafeLetWithReturn.kt + FUN name:foo visibility:public modality:FINAL <> (s:kotlin.String?) returnType:kotlin.String + VALUE_PARAMETER name:s index:0 type:kotlin.String? + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Nothing? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.String? [val] + GET_VAR 's: kotlin.String? declared in .foo' type=kotlin.String? origin=null + WHEN type=kotlin.Nothing? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_0: kotlin.String? [val] declared in .foo' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.StandardKt.let [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null + : kotlin.String + : kotlin.Nothing + $receiver: GET_VAR 'val tmp_0: kotlin.String? [val] declared in .foo' type=kotlin.String? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.Nothing + VALUE_PARAMETER name:it index:0 type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun foo (s: kotlin.String?): kotlin.String declared in ' + GET_VAR 'it: kotlin.String declared in .foo.' type=kotlin.String origin=null + RETURN type=kotlin.Nothing from='public final fun foo (s: kotlin.String?): kotlin.String declared in ' + CONST String type=kotlin.String value="" + FUN name:bar visibility:public modality:FINAL <> (s:kotlin.String?, t:kotlin.String?) returnType:kotlin.String + VALUE_PARAMETER name:s index:0 type:kotlin.String? + VALUE_PARAMETER name:t index:1 type:kotlin.String? + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Nothing? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.String? [val] + GET_VAR 's: kotlin.String? declared in .bar' type=kotlin.String? origin=null + WHEN type=kotlin.Nothing? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_1: kotlin.String? [val] declared in .bar' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.StandardKt.let [inline] declared in kotlin.StandardKt' type=kotlin.Nothing? origin=null + : kotlin.String + : kotlin.Nothing? + $receiver: GET_VAR 'val tmp_1: kotlin.String? [val] declared in .bar' type=kotlin.String? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.Nothing? + VALUE_PARAMETER name:it index:0 type:kotlin.String + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Nothing? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.String? [val] + GET_VAR 't: kotlin.String? declared in .bar' type=kotlin.String? origin=null + WHEN type=kotlin.Nothing? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_2: kotlin.String? [val] declared in .bar.' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.StandardKt.let [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null + : kotlin.String + : kotlin.Nothing + $receiver: GET_VAR 'val tmp_2: kotlin.String? [val] declared in .bar.' type=kotlin.String? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.Nothing + VALUE_PARAMETER name:it index:0 type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun bar (s: kotlin.String?, t: kotlin.String?): kotlin.String declared in ' + GET_VAR 'it: kotlin.String declared in .bar..' type=kotlin.String origin=null + RETURN type=kotlin.Nothing from='public final fun bar (s: kotlin.String?, t: kotlin.String?): kotlin.String declared in ' + CONST String type=kotlin.String value="" + PROPERTY name:baz visibility:public modality:FINAL [val] + FUN name: visibility:public modality:FINAL <> ($receiver:kotlin.String?) returnType:kotlin.String + correspondingProperty: PROPERTY name:baz visibility:public modality:FINAL [val] + $receiver: VALUE_PARAMETER name: type:kotlin.String? + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + BLOCK type=kotlin.Nothing? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.String? [val] + GET_VAR ': kotlin.String? declared in .' type=kotlin.String? origin=null + WHEN type=kotlin.Nothing? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_3: kotlin.String? [val] declared in .' type=kotlin.String? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.StandardKt.let [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null + : kotlin.String + : kotlin.Nothing + $receiver: GET_VAR 'val tmp_3: kotlin.String? [val] declared in .' type=kotlin.String? origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String) returnType:kotlin.Nothing + VALUE_PARAMETER name:it index:0 type:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in ' + GET_VAR 'it: kotlin.String declared in ..' type=kotlin.String origin=null + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in ' + CONST String type=kotlin.String value="" diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java index 9f6dbe9f456..47055458097 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java @@ -2182,6 +2182,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest { runTest("compiler/testData/ir/irText/firProblems/recursiveCapturedTypeInPropertyReference.kt"); } + @Test + @TestMetadata("SafeLetWithReturn.kt") + public void testSafeLetWithReturn() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/SafeLetWithReturn.kt"); + } + @Test @TestMetadata("SameJavaFieldReferences.kt") public void testSameJavaFieldReferences() throws Exception { From 1c210c23862273dba592a6a1032e77fddb8073cd Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 5 Feb 2021 17:15:15 +0300 Subject: [PATCH 016/153] FIR: fix of super.methodOfAny resolve in case of one supertype --- .../org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt | 5 +++-- .../withMethodOfAnyOverridenInInterface.fir.kt | 8 -------- .../withMethodOfAnyOverridenInInterface.kt | 1 + 3 files changed, 4 insertions(+), 10 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOfAnyOverridenInInterface.fir.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt index 02a97a20dde..4e3a683cc93 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt @@ -36,12 +36,13 @@ fun BodyResolveComponents.findTypesForSuperCandidates( containingCall: FirQualifiedAccess, ): Collection { val supertypes = superTypeRefs.map { (it as FirResolvedTypeRef).type } - if (supertypes.size <= 1) return supertypes + val isMethodOfAny = containingCall is FirFunctionCall && isCallingMethodOfAny(containingCall) + if (supertypes.size <= 1 && !isMethodOfAny) return supertypes return when (containingCall) { is FirFunctionCall -> { val calleeName = containingCall.calleeReference.name - if (isCallingMethodOfAny(containingCall)) { + if (isMethodOfAny) { resolveSupertypesForMethodOfAny(supertypes, calleeName) } else { resolveSupertypesByCalleeName(supertypes, calleeName) diff --git a/compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOfAnyOverridenInInterface.fir.kt b/compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOfAnyOverridenInInterface.fir.kt deleted file mode 100644 index 209e68c9f15..00000000000 --- a/compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOfAnyOverridenInInterface.fir.kt +++ /dev/null @@ -1,8 +0,0 @@ -interface IWithToString { - override fun toString(): String -} - -class A : IWithToString { - // Should be Any#toString(), even though IWithToString defines an abstract toString. - override fun toString(): String = super.toString() -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOfAnyOverridenInInterface.kt b/compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOfAnyOverridenInInterface.kt index ba5f4f70298..38c2975daef 100644 --- a/compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOfAnyOverridenInInterface.kt +++ b/compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOfAnyOverridenInInterface.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface IWithToString { override fun toString(): String } From 2cbdad0bb177205166d4e4228382c175b9bfa81b Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 5 Feb 2021 18:32:17 +0300 Subject: [PATCH 017/153] FIR2IR: insert implicit cast of receiver to Any for interface Any calls --- .../generators/CallAndReferenceGenerator.kt | 19 ++++++++++++++++++- .../hashCode/interfaceHashCode.kt | 1 - 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 4657a143edf..50463b06569 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.backend.generators +import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.declarations.* @@ -731,7 +732,23 @@ class CallAndReferenceGenerator( symbol.owner as? IrFunction ?: (symbol.owner as? IrProperty)?.getter if (ownerFunction?.dispatchReceiverParameter != null) { - dispatchReceiver = qualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression) + val baseDispatchReceiver = qualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression) + dispatchReceiver = + if (!ownerFunction.isMethodOfAny() || baseDispatchReceiver?.type?.classOrNull?.owner?.isInterface != true) { + baseDispatchReceiver + } else { + // NB: for FE 1.0, this type cast is added by InterfaceObjectCallsLowering + // However, it doesn't work for FIR due to different f/o structure + // (FIR calls Any method directly, but FE 1.0 calls its interface f/o instead) + IrTypeOperatorCallImpl( + baseDispatchReceiver.startOffset, + baseDispatchReceiver.endOffset, + irBuiltIns.anyType, + IrTypeOperator.IMPLICIT_CAST, + irBuiltIns.anyType, + baseDispatchReceiver + ) + } } if (ownerFunction?.extensionReceiverParameter != null) { extensionReceiver = qualifiedAccess.findIrExtensionReceiver(explicitReceiverExpression)?.let { diff --git a/compiler/testData/codegen/bytecodeText/hashCode/interfaceHashCode.kt b/compiler/testData/codegen/bytecodeText/hashCode/interfaceHashCode.kt index c6758916d84..c236203d714 100644 --- a/compiler/testData/codegen/bytecodeText/hashCode/interfaceHashCode.kt +++ b/compiler/testData/codegen/bytecodeText/hashCode/interfaceHashCode.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR val x: () -> Unit = {} val y = x.hashCode() From d4b0688690b2e291de060c1bf393217e38ae0f0c Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 2 Feb 2021 17:51:11 +0300 Subject: [PATCH 018/153] FIR: introduce delegate field initializers Before this commit we initialized delegate fields in primary constructor, that could provoke NPE in case delegate is used in initializer of some property backing field. Now we initialize delegate fields directly instead. --- .../resolve/delegatedSuperType.fir.txt | 5 +- .../anonymousObjectByDelegate.fir.txt | 10 +- .../diagnostics/delegationInInterface.fir.txt | 4 +- .../diagnostics/delegationInInterface.kt | 2 +- .../superCallWithDelegation.fir.txt | 5 +- .../kotlin/fir/backend/Fir2IrConverter.kt | 10 +- .../fir/backend/Fir2IrDeclarationStorage.kt | 11 +- .../kotlin/fir/backend/Fir2IrVisitor.kt | 4 +- .../generators/ClassMemberGenerator.kt | 12 ++ .../FirBlackBoxCodegenTestGenerated.java | 6 + .../runners/ir/Fir2IrTextTestGenerated.java | 6 + .../fir/java/declarations/FirJavaField.kt | 1 - .../converter/DeclarationsConverter.kt | 93 ++------- .../kotlin/fir/builder/RawFirBuilder.kt | 67 ++----- .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 12 ++ .../kotlin/fir/resolve/dfa/cfg/CFGNode.kt | 21 +++ .../fir/resolve/dfa/cfg/CFGNodeRenderer.kt | 2 + .../fir/resolve/dfa/cfg/ControlFlowGraph.kt | 1 + .../dfa/cfg/ControlFlowGraphBuilder.kt | 31 ++- .../dfa/cfg/ControlFlowGraphNodeBuilder.kt | 6 + .../dfa/cfg/ControlFlowGraphVisitor.kt | 10 + .../transformers/FirTypeResolveTransformer.kt | 13 +- .../body/resolve/FirBodyResolveTransformer.kt | 4 + .../FirDeclarationsResolveTransformer.kt | 30 +++ .../FirContractResolveTransformer.kt | 5 + .../impl/FirClassDeclaredMemberScope.kt | 2 +- .../declarations/builder/FirFieldBuilder.kt | 2 + .../fir/declarations/impl/FirFieldImpl.kt | 9 +- .../generator/ImplementationConfigurator.kt | 2 +- .../box/fir/Fir2IrClassifierStorage.kt | 28 +++ .../delegatedGenericImplementation.fir.kt.txt | 15 +- .../delegatedGenericImplementation.fir.txt | 48 +++-- .../delegatedImplementation.fir.kt.txt | 9 +- .../classes/delegatedImplementation.fir.txt | 19 +- ...edImplementationOfJavaInterface.fir.kt.txt | 10 +- ...gatedImplementationOfJavaInterface.fir.txt | 27 ++- ...lementationWithExplicitOverride.fir.kt.txt | 8 +- ...ImplementationWithExplicitOverride.fir.txt | 15 +- ...otNullOnDelegatedImplementation.fir.kt.txt | 15 +- ...itNotNullOnDelegatedImplementation.fir.txt | 25 +-- .../annotationsOnDelegatedMembers.fir.kt.txt | 3 +- .../annotationsOnDelegatedMembers.fir.txt | 5 +- .../inheritingDeprecation.fir.kt.txt | 3 +- .../annotations/inheritingDeprecation.fir.txt | 5 +- .../ir/irText/declarations/kt35550.fir.kt.txt | 3 +- .../ir/irText/declarations/kt35550.fir.txt | 5 +- .../parameters/delegatedMembers.fir.kt.txt | 3 +- .../parameters/delegatedMembers.fir.txt | 5 +- .../firProblems/AnnotationLoader.fir.kt.txt | 8 +- .../firProblems/AnnotationLoader.fir.txt | 15 +- ...elegationAndInheritanceFromJava.fir.kt.txt | 3 +- .../DelegationAndInheritanceFromJava.fir.txt | 5 +- .../Fir2IrClassifierStorage.fir.kt.txt | 66 +++++++ .../Fir2IrClassifierStorage.fir.txt | 176 ++++++++++++++++++ .../firProblems/Fir2IrClassifierStorage.kt | 18 ++ .../Fir2IrClassifierStorage.kt.txt | 65 +++++++ .../firProblems/Fir2IrClassifierStorage.txt | 173 +++++++++++++++++ .../firProblems/SignatureClash.fir.kt.txt | 11 +- .../irText/firProblems/SignatureClash.fir.txt | 23 ++- .../ir/irText/firProblems/kt43342.fir.kt.txt | 10 +- .../ir/irText/firProblems/kt43342.fir.txt | 27 ++- .../irText/types/javaWildcardType.fir.kt.txt | 6 +- .../ir/irText/types/javaWildcardType.fir.txt | 10 +- .../types/rawTypeInSignature.fir.kt.txt | 3 +- .../irText/types/rawTypeInSignature.fir.txt | 5 +- .../codegen/BlackBoxCodegenTestGenerated.java | 6 + .../IrBlackBoxCodegenTestGenerated.java | 6 + .../test/runners/ir/IrTextTestGenerated.java | 6 + .../LightAnalysisModeTestGenerated.java | 5 + 69 files changed, 928 insertions(+), 356 deletions(-) create mode 100644 compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt create mode 100644 compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.fir.kt.txt create mode 100644 compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.fir.txt create mode 100644 compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt create mode 100644 compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt.txt create mode 100644 compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/delegatedSuperType.fir.txt b/compiler/fir/analysis-tests/testData/resolve/delegatedSuperType.fir.txt index 44fedf60655..750ae3ad097 100644 --- a/compiler/fir/analysis-tests/testData/resolve/delegatedSuperType.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/delegatedSuperType.fir.txt @@ -13,13 +13,12 @@ FILE: delegatedSuperType.kt } public final class C : R|A| { - local final field <$$delegate_0>: R|A| - public constructor(b: R|B|): R|C| { super() - this@R|/C|.R|/<$$delegate_0>| = R|/b| } + local final field <$$delegate_0>: R|A| = R|/b| + public final val b: R|B| = R|/b| public get(): R|B| diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/anonymousObjectByDelegate.fir.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/anonymousObjectByDelegate.fir.txt index d83ecbdb10b..cc3f18011e9 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/anonymousObjectByDelegate.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/anonymousObjectByDelegate.fir.txt @@ -9,25 +9,23 @@ FILE: anonymousObjectByDelegate.kt } public final fun R|A|.test_1(): R|kotlin/Unit| { object : R|B| { - local final field <$$delegate_0>: R|B| - private constructor(): R|| { super() - this@R|/|.R|/<$$delegate_0>| = this@R|/test_1|.R|/A.b| } + local final field <$$delegate_0>: R|B| = this@R|/test_1|.R|/A.b| + } } public final fun R|A|.test_2(): R|kotlin/Unit| { object : R|B| { - local final field <$$delegate_0>: R|B| - private constructor(): R|| { super() - this@R|/|.R|/<$$delegate_0>| = this@R|/test_2|.R|/A.b| } + local final field <$$delegate_0>: R|B| = this@R|/test_2|.R|/A.b| + } } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationInInterface.fir.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationInInterface.fir.txt index daa35ef4ecf..9c39bfa07c9 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationInInterface.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationInInterface.fir.txt @@ -6,7 +6,7 @@ FILE: delegationInInterface.kt } public abstract interface B : R|A| { - local final field <$$delegate_0>: R|A| + local final field <$$delegate_0>: R|A| = # public abstract val a: R|A| public get(): R|A| @@ -15,6 +15,6 @@ FILE: delegationInInterface.kt public final val test: R|A| = R|/A.A|() public get(): R|A| public abstract interface C : R|A| { - local final field <$$delegate_0>: R|A| + local final field <$$delegate_0>: R|A| = R|/test| } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationInInterface.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationInInterface.kt index b212a508b3c..cd5318b99c4 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationInInterface.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/delegationInInterface.kt @@ -1,6 +1,6 @@ class A -interface B : A by a { +interface B : A by a { val a: A } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/superCallWithDelegation.fir.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/superCallWithDelegation.fir.txt index 728990c69a9..c761b0afb53 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/superCallWithDelegation.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/superCallWithDelegation.fir.txt @@ -4,13 +4,12 @@ FILE: superCallWithDelegation.kt } public open class B : R|A| { - local final field <$$delegate_0>: R|A| - public constructor(a: R|A|): R|B| { super() - this@R|/B|.R|/<$$delegate_0>| = R|/a| } + local final field <$$delegate_0>: R|A| = R|/a| + private final val a: R|A| = R|/a| private get(): R|A| diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index a07d8e84ec4..dcb27fa4ade 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -93,7 +93,7 @@ class Fir2IrConverter( } val processedCallableNames = mutableSetOf() val classes = mutableListOf() - for (declaration in sortBySynthetic(anonymousObject.declarations)) { + for (declaration in syntheticPropertiesLast(anonymousObject.declarations)) { val irDeclaration = if (declaration is FirRegularClass) { classes += declaration registerClassAndNestedClasses(declaration, irClass) @@ -129,7 +129,7 @@ class Fir2IrConverter( irClass.declarations += irConstructor } val allDeclarations = regularClass.declarations.toMutableList() - for (declaration in sortBySynthetic(regularClass.declarations)) { + for (declaration in syntheticPropertiesLast(regularClass.declarations)) { val irDeclaration = processMemberDeclaration(declaration, regularClass, irClass) ?: continue irClass.declarations += irDeclaration } @@ -167,8 +167,8 @@ class Fir2IrConverter( // Sort declarations so that all non-synthetic declarations are before synthetic ones. // This is needed because converting synthetic fields for implementation delegation needs to know // existing declarations in the class to avoid adding redundant delegated members. - private fun sortBySynthetic(declarations: List): Iterable { - return declarations.sortedBy { it.isSynthetic } + private fun syntheticPropertiesLast(declarations: List): Iterable { + return declarations.sortedBy { it !is FirField && it.isSynthetic } } private fun registerClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass { @@ -273,7 +273,7 @@ class Fir2IrConverter( val classifierStorage = Fir2IrClassifierStorage(components) val converter = Fir2IrConverter(moduleDescriptor, sourceManager, components) val fir2irVisitor = Fir2IrVisitor(converter, components, conversionScope) - val declarationStorage = Fir2IrDeclarationStorage(components, fir2irVisitor, moduleDescriptor) + val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor) val typeConverter = Fir2IrTypeConverter(components) val builtIns = Fir2IrBuiltIns(components, specialSymbolProvider) val annotationGenerator = AnnotationGenerator(components) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index d1c4e41dcb1..5e82c4488ff 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -39,7 +39,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass -import org.jetbrains.kotlin.ir.descriptors.* import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl @@ -56,7 +55,6 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ @OptIn(ObsoleteDescriptorBasedAPI::class) class Fir2IrDeclarationStorage( private val components: Fir2IrComponents, - private val visitor: Fir2IrVisitor, private val moduleDescriptor: FirModuleDescriptor ) : Fir2IrComponents by components { @@ -850,12 +848,11 @@ class Fir2IrDeclarationStorage( isExternal = false, isStatic = field.isStatic ).apply { - field.initializer?.let { - val expression = visitor.convertToIrExpression(it) - expression.type = type - initializer = irFactory.createExpressionBody(expression) - } fieldCache[field] = this + val initializer = field.initializer + if (initializer is FirConstExpression<*>) { + this.initializer = factory.createExpressionBody(initializer.toIrConst(type)) + } } } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index b6f40c35c39..84ae8b8a250 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -67,7 +67,9 @@ class Fir2IrVisitor( override fun visitField(field: FirField, data: Any?): IrField { if (field.isSynthetic) { - return declarationStorage.getCachedIrField(field)!! + return declarationStorage.getCachedIrField(field)!!.apply { + memberGenerator.convertFieldContent(this, field) + } } else { throw AssertionError("Unexpected field: ${field.render()}") } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index aa43ea3c266..0b709411cfb 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -174,6 +174,18 @@ internal class ClassMemberGenerator( return irProperty } + fun convertFieldContent(irField: IrField, field: FirField): IrField { + conversionScope.withParent(irField) { + declarationStorage.enterScope(irField) + val initializerExpression = field.initializer + if (irField.initializer == null && initializerExpression != null) { + irField.initializer = irFactory.createExpressionBody(visitor.convertToIrExpression(initializerExpression)) + } + declarationStorage.leaveScope(irField) + } + return irField + } + private fun IrProperty.initializeBackingField( property: FirProperty, initializerExpression: FirExpression? diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 70f85227e17..2bea9176c2b 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -14840,6 +14840,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/fir/FakeOverrideBuilder.kt"); } + @Test + @TestMetadata("Fir2IrClassifierStorage.kt") + public void testFir2IrClassifierStorage() throws Exception { + runTest("compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt"); + } + @Test @TestMetadata("IrBuiltIns.kt") public void testIrBuiltIns() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java index 7bd135d100f..6c0c63e55c0 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java @@ -2116,6 +2116,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/firProblems/deprecated.kt"); } + @Test + @TestMetadata("Fir2IrClassifierStorage.kt") + public void testFir2IrClassifierStorage() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt"); + } + @Test @TestMetadata("FirBuilder.kt") public void testFirBuilder() throws Exception { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaField.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaField.kt index e2c5c420af1..723e21bf066 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaField.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaField.kt @@ -148,7 +148,6 @@ internal class FirJavaFieldBuilder : FirFieldBuilder() { var modality: Modality? = null lateinit var visibility: Visibility var isStatic: Boolean by Delegates.notNull() - var initializer: FirExpression? = null lateinit var annotationBuilder: () -> List override var resolvePhase: FirResolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 283b1afb22b..e4acbaa0b71 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -37,12 +37,9 @@ import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeModifier import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeParameterModifier import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeProjectionModifier -import org.jetbrains.kotlin.fir.references.builder.buildImplicitThisReference -import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations import org.jetbrains.kotlin.fir.scopes.FirScopeProvider -import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.LocalCallableIdConstructor import org.jetbrains.kotlin.fir.symbols.impl.* @@ -432,10 +429,9 @@ class DeclarationsConverter( val selfType = classNode.toDelegatedSelfType(this) registerSelfType(selfType) - val delegationSpecifiers = superTypeList?.let { convertDelegationSpecifiers(it, symbol, selfType) } + val delegationSpecifiers = superTypeList?.let { convertDelegationSpecifiers(it) } var delegatedSuperTypeRef: FirTypeRef? = delegationSpecifiers?.delegatedSuperTypeRef val delegatedConstructorSource: FirLightSourceElement? = delegationSpecifiers?.delegatedConstructorSource - delegationSpecifiers?.delegateFields?.map { declarations += it } val superTypeCallEntry = delegationSpecifiers?.delegatedConstructorArguments.orEmpty() val superTypeRefs = mutableListOf() @@ -479,11 +475,11 @@ class DeclarationsConverter( ) //parse primary constructor val primaryConstructorWrapper = convertPrimaryConstructor( - primaryConstructor, selfType.source, classWrapper, delegatedConstructorSource, - delegationSpecifiers?.primaryConstructorBody + primaryConstructor, selfType.source, classWrapper, delegatedConstructorSource ) val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor firPrimaryConstructor?.let { declarations += it } + delegationSpecifiers?.delegateFields?.map { declarations += it } val properties = mutableListOf() if (primaryConstructor != null && firPrimaryConstructor != null) { @@ -558,19 +554,17 @@ class DeclarationsConverter( var classBody: LighterASTNode? = null var delegatedConstructorSource: FirLightSourceElement? = null var delegateFields: List? = null - var primaryConstructorBody: FirBlock? = null objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first().forEachChildren { when (it.tokenType) { MODIFIER_LIST -> modifiers = convertModifierList(it) PRIMARY_CONSTRUCTOR -> primaryConstructor = it - SUPER_TYPE_LIST -> convertDelegationSpecifiers(it, symbol, delegatedSelfType).let { - delegatedSuperTypeRef = it.delegatedSuperTypeRef - superTypeRefs += it.superTypesRef - superTypeCallEntry += it.delegatedConstructorArguments - delegatedConstructorSource = it.delegatedConstructorSource - delegateFields = it.delegateFields - primaryConstructorBody = it.primaryConstructorBody + SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).let { specifiers -> + delegatedSuperTypeRef = specifiers.delegatedSuperTypeRef + superTypeRefs += specifiers.superTypesRef + superTypeCallEntry += specifiers.delegatedConstructorArguments + delegatedConstructorSource = specifiers.delegatedConstructorSource + delegateFields = specifiers.delegateFields } CLASS_BODY -> classBody = it } @@ -586,7 +580,6 @@ class DeclarationsConverter( this.superTypeRefs += superTypeRefs typeRef = delegatedSelfType - delegateFields?.map { this.declarations += it } val classWrapper = ClassWrapper( SpecialNames.NO_NAME_PROVIDED, modifiers, ClassKind.OBJECT, this, hasPrimaryConstructor = false, @@ -597,8 +590,10 @@ class DeclarationsConverter( superTypeCallEntry = superTypeCallEntry ) //parse primary constructor - convertPrimaryConstructor(primaryConstructor, typeRef.source, classWrapper, delegatedConstructorSource, primaryConstructorBody) - ?.let { this.declarations += it.firConstructor } + convertPrimaryConstructor( + primaryConstructor, typeRef.source, classWrapper, delegatedConstructorSource + )?.let { this.declarations += it.firConstructor } + delegateFields?.let { this.declarations += it } //parse declarations classBody?.let { @@ -724,7 +719,6 @@ class DeclarationsConverter( selfTypeSource: FirSourceElement?, classWrapper: ClassWrapper, delegatedConstructorSource: FirLightSourceElement?, - body: FirBlock? = null ): PrimaryConstructor? { if (primaryConstructor == null && !classWrapper.isEnumEntry() && classWrapper.hasSecondaryConstructor) return null if (classWrapper.isInterface()) return null @@ -768,7 +762,7 @@ class DeclarationsConverter( typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters) this.valueParameters += valueParameters.map { it.firValueParameter } delegatedConstructor = firDelegatedCall - this.body = body + this.body = null }.apply { containingClassAttr = currentDispatchReceiverType()!!.lookupTag }, valueParameters @@ -1437,21 +1431,14 @@ class DeclarationsConverter( val delegatedConstructorArguments: List, val delegatedConstructorSource: FirLightSourceElement?, val delegateFields: List, - val primaryConstructorBody: FirBlock? ) - private fun convertDelegationSpecifiers( - delegationSpecifiers: LighterASTNode, - containerSymbol: AbstractFirBasedSymbol<*>, - delegatedTypeRef: FirTypeRef - ): DelegationSpecifiers { + private fun convertDelegationSpecifiers(delegationSpecifiers: LighterASTNode): DelegationSpecifiers { val superTypeRefs = mutableListOf() val superTypeCallEntry = mutableListOf() var delegatedSuperTypeRef: FirTypeRef? = null var delegateConstructorSource: FirLightSourceElement? = null val delegateFields = mutableListOf() - val initializeDelegateStatements = mutableListOf() - var delegateNumber = 0 delegationSpecifiers.forEachChildren { when (it.tokenType) { SUPER_TYPE_ENTRY -> { @@ -1464,28 +1451,12 @@ class DeclarationsConverter( delegateConstructorSource = it.toFirSourceElement(FirFakeSourceElementKind.DelegatingConstructorCall) } DELEGATED_SUPER_TYPE_ENTRY -> { - superTypeRefs += convertExplicitDelegation( - it, - delegateNumber, - delegateFields, - initializeDelegateStatements, - containerSymbol, - delegatedTypeRef - ) - delegateNumber++ + superTypeRefs += convertExplicitDelegation(it, delegateFields) } } } - val body = if (initializeDelegateStatements.isNotEmpty()) { - buildBlock { - for (statement in initializeDelegateStatements) { - statements += statement - } - } - } else null return DelegationSpecifiers( - delegatedSuperTypeRef, superTypeRefs, superTypeCallEntry, delegateConstructorSource, - delegateFields, body + delegatedSuperTypeRef, superTypeRefs, superTypeCallEntry, delegateConstructorSource, delegateFields ) } @@ -1515,14 +1486,7 @@ class DeclarationsConverter( * : userType "by" element * ; */ - private fun convertExplicitDelegation( - explicitDelegation: LighterASTNode, - delegateNumber: Int, - delegateFields: MutableList, - initializeDelegateStatements: MutableList, - containerSymbol: AbstractFirBasedSymbol<*>, - delegatedSelfTypeRef: FirTypeRef - ): FirTypeRef { + private fun convertExplicitDelegation(explicitDelegation: LighterASTNode, delegateFields: MutableList): FirTypeRef { lateinit var firTypeRef: FirTypeRef var firExpression: FirExpression? = buildErrorExpression( explicitDelegation.toFirSourceElement(), ConeSimpleDiagnostic("Should have delegate", DiagnosticKind.Syntax) @@ -1534,7 +1498,7 @@ class DeclarationsConverter( } } - val delegateName = Name.special("<\$\$delegate_$delegateNumber>") + val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>") delegateFields.add( buildField { source = firExpression!!.source @@ -1545,24 +1509,7 @@ class DeclarationsConverter( symbol = FirFieldSymbol(@OptIn(LocalCallableIdConstructor::class) CallableId(name)) isVar = false status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) - } - ) - initializeDelegateStatements.add( - buildVariableAssignment { - source = firExpression!!.source - calleeReference = - buildResolvedNamedReference { - name = delegateName - resolvedSymbol = delegateFields[delegateNumber].symbol - } - rValue = firExpression!! - dispatchReceiver = buildThisReceiverExpression { - source = firExpression!!.source - calleeReference = buildImplicitThisReference { - boundSymbol = containerSymbol - } - typeRef = delegatedSelfTypeRef - } + initializer = firExpression } ) return firTypeRef diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 7c23143efdb..3959e85a96a 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -28,7 +28,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.scopes.FirScopeProvider -import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.LocalCallableIdConstructor import org.jetbrains.kotlin.fir.symbols.impl.* @@ -544,13 +543,11 @@ class RawFirBuilder( delegatedSelfTypeRef: FirTypeRef?, delegatedEnumSuperTypeRef: FirTypeRef?, classKind: ClassKind, - containerTypeParameters: List, - containerSymbol: AbstractFirBasedSymbol<*> + containerTypeParameters: List ): FirTypeRef { var superTypeCallEntry: KtSuperTypeCallEntry? = null var delegatedSuperTypeRef: FirTypeRef? = null - var delegateNumber = 0 - val initializeDelegateStatements = mutableListOf() + val delegateFields = mutableListOf() for (superTypeListEntry in superTypeListEntries) { when (superTypeListEntry) { is KtSuperTypeEntry -> { @@ -565,7 +562,7 @@ class RawFirBuilder( val type = superTypeListEntry.typeReference.toFirOrErrorType() val delegateExpression = { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate") container.superTypeRefs += type - val delegateName = Name.special("<\$\$delegate_$delegateNumber>") + val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>") val delegateSource = superTypeListEntry.delegateExpression?.toFirSourceElement() val delegateField = buildField { source = delegateSource @@ -576,28 +573,9 @@ class RawFirBuilder( symbol = FirFieldSymbol(@OptIn(LocalCallableIdConstructor::class) CallableId(name)) isVar = false status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) + initializer = delegateExpression } - initializeDelegateStatements.add( - buildVariableAssignment { - source = delegateSource - calleeReference = - buildResolvedNamedReference { - source = delegateSource - name = delegateName - resolvedSymbol = delegateField.symbol - } - rValue = delegateExpression - dispatchReceiver = buildThisReceiverExpression { - source = delegateSource - calleeReference = buildImplicitThisReference { - boundSymbol = containerSymbol - } - delegatedSelfTypeRef?.let { typeRef = it } - } - } - ) - container.declarations.add(delegateField) - delegateNumber++ + delegateFields.add(delegateField) } } } @@ -637,27 +615,22 @@ class RawFirBuilder( container.superTypeRefs += implicitAnyType delegatedSuperTypeRef = implicitAnyType } - if (this is KtClass && this.isInterface()) return delegatedSuperTypeRef ?: implicitAnyType // TODO: in case we have no primary constructor, // it may be not possible to determine delegated super type right here delegatedSuperTypeRef = delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef - if (!this.hasPrimaryConstructor()) return delegatedSuperTypeRef - - val firPrimaryConstructor = primaryConstructor.toFirConstructor( - superTypeCallEntry, - delegatedSuperTypeRef, - delegatedSelfTypeRef ?: delegatedSuperTypeRef, - owner = this, - containerTypeParameters, - body = if (initializeDelegateStatements.isNotEmpty()) buildBlock { - for (statement in initializeDelegateStatements) { - statements += statement - } - } else null - ) - - container.declarations += firPrimaryConstructor + if ((this !is KtClass || !this.isInterface()) && this.hasPrimaryConstructor()) { + val firPrimaryConstructor = primaryConstructor.toFirConstructor( + superTypeCallEntry, + delegatedSuperTypeRef, + delegatedSelfTypeRef ?: delegatedSuperTypeRef, + owner = this, + containerTypeParameters, + body = null + ) + container.declarations += firPrimaryConstructor + } + container.declarations += delegateFields return delegatedSuperTypeRef } @@ -861,8 +834,7 @@ class RawFirBuilder( delegatedSelfType, null, classKind, - typeParameters, - symbol + typeParameters ) val primaryConstructor = classOrObject.primaryConstructor @@ -947,8 +919,7 @@ class RawFirBuilder( delegatedSelfType, null, ClassKind.CLASS, - containerTypeParameters = emptyList(), - symbol + containerTypeParameters = emptyList() ) typeRef = delegatedSelfType 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 58e5d30c9b8..6d3b14621f3 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 @@ -268,6 +268,18 @@ abstract class FirDataFlowAnalyzer( return graph } + // ----------------------------------- Field ----------------------------------- + + fun enterField(field: FirField) { + graphBuilder.enterField(field)?.mergeIncomingFlow() + } + + fun exitField(field: FirField): ControlFlowGraph? { + val (node, graph) = graphBuilder.exitField(field) ?: return null + node.mergeIncomingFlow() + return graph + } + // ----------------------------------- Delegate ----------------------------------- fun enterDelegateExpression() { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt index 2a81173d62d..d344fd43af6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt @@ -280,6 +280,27 @@ class PropertyInitializerExitNode(owner: ControlFlowGraph, override val fir: Fir } } +// ----------------------------------- Field ----------------------------------- + +class FieldInitializerEnterNode(owner: ControlFlowGraph, override val fir: FirField, level: Int, id: Int) : CFGNode(owner, level, id), EnterNodeMarker { + init { + owner.enterNode = this + } + + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + return visitor.visitFieldInitializerEnterNode(this, data) + } +} +class FieldInitializerExitNode(owner: ControlFlowGraph, override val fir: FirField, level: Int, id: Int) : CFGNode(owner, level, id), ExitNodeMarker { + init { + owner.exitNode = this + } + + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + return visitor.visitFieldInitializerExitNode(this, data) + } +} + // ----------------------------------- Init ----------------------------------- class InitBlockEnterNode(owner: ControlFlowGraph, override val fir: FirAnonymousInitializer, level: Int, id: Int) : CFGNode(owner, level, id), EnterNodeMarker { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt index 9dd65782c22..f73f78bf965 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt @@ -85,6 +85,8 @@ fun CFGNode<*>.render(): String = is PartOfClassInitializationNode -> "Part of class initialization" is PropertyInitializerEnterNode -> "Enter property" is PropertyInitializerExitNode -> "Exit property" + is FieldInitializerEnterNode -> "Enter field" + is FieldInitializerExitNode -> "Exit field" is InitBlockEnterNode -> "Enter init block" is InitBlockExitNode -> "Exit init block" is AnnotationEnterNode -> "Enter annotation" diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt index 7d21f20d2de..699fcbefd99 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt @@ -80,6 +80,7 @@ class ControlFlowGraph(val declaration: FirDeclaration?, val name: String, val k AnonymousFunction(withBody = true), ClassInitializer(withBody = true), PropertyInitializer(withBody = true), + FieldInitializer(withBody = true), TopLevel(withBody = false), AnnotationCall(withBody = true), DefaultArgument(withBody = false), diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 8bb8403593d..f9b62f6427b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -58,7 +58,7 @@ class ControlFlowGraphBuilder { private val shouldPassFlowFromInplaceLambda: Stack = stackOf(true) private enum class Mode { - Function, TopLevel, Body, ClassInitializer, PropertyInitializer + Function, TopLevel, Body, ClassInitializer, PropertyInitializer, FieldInitializer } // ----------------------------------- Node caches ----------------------------------- @@ -522,6 +522,35 @@ class ControlFlowGraphBuilder { return exitNode to graph } + // ----------------------------------- Field ----------------------------------- + + fun enterField(field: FirField): FieldInitializerEnterNode? { + if (field.initializer == null) return null + + val graph = ControlFlowGraph(field, "val ${field.name}", ControlFlowGraph.Kind.FieldInitializer) + pushGraph(graph, Mode.FieldInitializer) + + val enterNode = createFieldInitializerEnterNode(field) + val exitNode = createFieldInitializerExitNode(field) + exitTargetsForTry.push(exitNode) + + enterToLocalClassesMembers[field.symbol]?.let { + addEdge(it, enterNode, preferredKind = EdgeKind.DfgForward) + } + + lastNodes.push(enterNode) + return enterNode + } + + fun exitField(field: FirField): Pair? { + if (field.initializer == null) return null + val exitNode = exitTargetsForTry.pop() as FieldInitializerExitNode + popAndAddEdge(exitNode) + val graph = popGraph() + assert(exitNode == graph.exitNode) + return exitNode to graph + } + // ----------------------------------- Delegate ----------------------------------- fun enterDelegateExpression() { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt index 2d8a69826d3..551984f9e0c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt @@ -58,6 +58,12 @@ fun ControlFlowGraphBuilder.createPropertyInitializerExitNode(fir: FirProperty): fun ControlFlowGraphBuilder.createPropertyInitializerEnterNode(fir: FirProperty): PropertyInitializerEnterNode = PropertyInitializerEnterNode(currentGraph, fir, levelCounter, createId()) +fun ControlFlowGraphBuilder.createFieldInitializerExitNode(fir: FirField): FieldInitializerExitNode = + FieldInitializerExitNode(currentGraph, fir, levelCounter, createId()) + +fun ControlFlowGraphBuilder.createFieldInitializerEnterNode(fir: FirField): FieldInitializerEnterNode = + FieldInitializerEnterNode(currentGraph, fir, levelCounter, createId()) + fun ControlFlowGraphBuilder.createFunctionEnterNode(fir: FirFunction<*>): FunctionEnterNode = FunctionEnterNode(currentGraph, fir, levelCounter, createId()).also { currentGraph.enterNode = it diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt index cb5fc522cc6..a8c9d98eafe 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt @@ -80,6 +80,16 @@ abstract class ControlFlowGraphVisitor { return visitNode(node, data) } + // ----------------------------------- Field ----------------------------------- + + open fun visitFieldInitializerEnterNode(node: FieldInitializerEnterNode, data: D): R { + return visitNode(node, data) + } + + open fun visitFieldInitializerExitNode(node: FieldInitializerExitNode, data: D): R { + return visitNode(node, data) + } + // ----------------------------------- Init ----------------------------------- open fun visitInitBlockEnterNode(node: InitBlockEnterNode, data: D): R { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt index 426637818ff..64bbe27c43f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt @@ -19,7 +19,10 @@ import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.compose -class FirTypeResolveProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) { +class FirTypeResolveProcessor( + session: FirSession, + scopeSession: ScopeSession +) : FirTransformerBasedResolveProcessor(session, scopeSession) { override val transformer = FirTypeResolveTransformer(session, scopeSession) } @@ -116,6 +119,14 @@ class FirTypeResolveTransformer( } } + override fun transformField(field: FirField, data: Nothing?): CompositeTransformResult { + return withScopeCleanup { + field.replaceResolvePhase(FirResolvePhase.TYPES) + field.transformReturnTypeRef(this, data).transformAnnotations(this, data) + field.compose() + } + } + override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Nothing?): CompositeTransformResult { return withScopeCleanup { simpleFunction.addTypeParametersScope() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt index d127e062ea9..976f182f23c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt @@ -259,6 +259,10 @@ open class FirBodyResolveTransformer( return declarationsTransformer.transformProperty(property, data) } + override fun transformField(field: FirField, data: ResolutionMode): CompositeTransformResult { + return declarationsTransformer.transformField(field, data) + } + override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): CompositeTransformResult { return declarationsTransformer.transformRegularClass(regularClass, data) } 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 826950c76fc..93905dbcd98 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 @@ -160,6 +160,36 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor } } + override fun transformField(field: FirField, data: ResolutionMode): CompositeTransformResult { + val returnTypeRef = field.returnTypeRef + if (implicitTypeOnly) return field.compose() + if (field.resolvePhase == transformerPhase) return field.compose() + if (field.resolvePhase == FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE && transformerPhase == FirResolvePhase.BODY_RESOLVE) { + transformer.replaceDeclarationResolvePhaseIfNeeded(field, transformerPhase) + return field.compose() + } + dataFlowAnalyzer.enterField(field) + return withFullBodyResolve { + withLocalScopeCleanup { + val primaryConstructorParametersScope = context.getPrimaryConstructorAllParametersScope() + context.withTowerDataContext(context.getTowerDataContextForConstructorResolution()) { + context.withContainer(field) { + withLocalScopeCleanup { + addLocalScope(primaryConstructorParametersScope) + field.transformChildren(transformer, withExpectedType(returnTypeRef)) + } + if (field.initializer != null) { + storeVariableReturnType(field) + } + } + } + transformer.replaceDeclarationResolvePhaseIfNeeded(field, transformerPhase) + dataFlowAnalyzer.exitField(field) + field.compose() + } + } + } + private fun FirFunctionCall.replacePropertyReferenceTypeInDelegateAccessors(property: FirProperty) { // var someProperty: SomeType // get() = delegate.getValue(thisRef, kProperty: KProperty0/1/2<..., SomeType>) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirContractResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirContractResolveTransformer.kt index 8d459fcd262..695041b861d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirContractResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirContractResolveTransformer.kt @@ -102,6 +102,11 @@ open class FirContractResolveTransformer( return property.compose() } + override fun transformField(field: FirField, data: ResolutionMode): CompositeTransformResult { + field.updatePhase() + return field.compose() + } + private fun transformPropertyAccessor( propertyAccessor: FirPropertyAccessor, owner: FirProperty diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassDeclaredMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassDeclaredMemberScope.kt index 9d85dfc5f7d..c5ee12605ad 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassDeclaredMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassDeclaredMemberScope.kt @@ -34,7 +34,7 @@ class FirClassDeclaredMemberScope( is FirCallableMemberDeclaration<*> -> { val name = when (declaration) { is FirConstructor -> CONSTRUCTOR_NAME - is FirVariable<*> -> declaration.name + is FirVariable<*> -> if (declaration.isSynthetic) continue@loop else declaration.name is FirSimpleFunction -> declaration.name else -> continue@loop } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirFieldBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirFieldBuilder.kt index eeec5befdb9..a4e41f30d4e 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirFieldBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirFieldBuilder.kt @@ -43,6 +43,7 @@ open class FirFieldBuilder : FirAnnotationContainerBuilder { open lateinit var returnTypeRef: FirTypeRef open lateinit var name: Name open lateinit var symbol: FirVariableSymbol + open var initializer: FirExpression? = null open var isVar: Boolean by kotlin.properties.Delegates.notNull() override val annotations: MutableList = mutableListOf() open val typeParameters: MutableList = mutableListOf() @@ -60,6 +61,7 @@ open class FirFieldBuilder : FirAnnotationContainerBuilder { returnTypeRef, name, symbol, + initializer, isVar, annotations, typeParameters, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt index 2ce4ce50aa6..532753588ff 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirFieldImpl.kt @@ -38,6 +38,7 @@ internal class FirFieldImpl( override var returnTypeRef: FirTypeRef, override val name: Name, override val symbol: FirVariableSymbol, + override var initializer: FirExpression?, override val isVar: Boolean, override val annotations: MutableList, override val typeParameters: MutableList, @@ -46,7 +47,6 @@ internal class FirFieldImpl( override val dispatchReceiverType: ConeKotlinType?, ) : FirField() { override val receiverTypeRef: FirTypeRef? get() = null - override val initializer: FirExpression? get() = null override val delegate: FirExpression? get() = null override val delegateFieldSymbol: FirDelegateFieldSymbol? get() = null override val isVal: Boolean get() = !isVar @@ -60,6 +60,7 @@ internal class FirFieldImpl( override fun acceptChildren(visitor: FirVisitor, data: D) { returnTypeRef.accept(visitor, data) + initializer?.accept(visitor, data) annotations.forEach { it.accept(visitor, data) } typeParameters.forEach { it.accept(visitor, data) } status.accept(visitor, data) @@ -67,6 +68,7 @@ internal class FirFieldImpl( override fun transformChildren(transformer: FirTransformer, data: D): FirFieldImpl { transformReturnTypeRef(transformer, data) + transformInitializer(transformer, data) transformTypeParameters(transformer, data) transformStatus(transformer, data) transformOtherChildren(transformer, data) @@ -83,6 +85,7 @@ internal class FirFieldImpl( } override fun transformInitializer(transformer: FirTransformer, data: D): FirFieldImpl { + initializer = initializer?.transformSingle(transformer, data) return this } @@ -128,5 +131,7 @@ internal class FirFieldImpl( override fun replaceReceiverTypeRef(newReceiverTypeRef: FirTypeRef?) {} - override fun replaceInitializer(newInitializer: FirExpression?) {} + override fun replaceInitializer(newInitializer: FirExpression?) { + initializer = newInitializer + } } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index c51fe91e63c..c705a4ce8af 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -210,7 +210,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() withGetter = true } - defaultNull("delegateFieldSymbol", "receiverTypeRef", "initializer", "delegate", "getter", "setter", withGetter = true) + defaultNull("delegateFieldSymbol", "receiverTypeRef", "delegate", "getter", "setter", withGetter = true) } impl(enumEntry) { diff --git a/compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt b/compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt new file mode 100644 index 00000000000..9eae51c0c5c --- /dev/null +++ b/compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt @@ -0,0 +1,28 @@ +// TARGET_BACKEND: JVM + +class FirSession(val name: String) + +interface Fir2IrComponents { + val session: FirSession + val classifierStorage: Fir2IrClassifierStorage +} + +class Fir2IrComponentsStorage( + override val session: FirSession +) : Fir2IrComponents { + override lateinit var classifierStorage: Fir2IrClassifierStorage +} + +class Fir2IrClassifierStorage( + private val components: Fir2IrComponents +) : Fir2IrComponents by components { + private val name = session.name +} + +fun box(): String { + val session = FirSession("OK") + val components = Fir2IrComponentsStorage(session) + val classifierStorage = Fir2IrClassifierStorage(components) + components.classifierStorage = classifierStorage + return classifierStorage.session.name +} diff --git a/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.kt.txt b/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.kt.txt index 4861e83dbf8..73650a6c7c9 100644 --- a/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.kt.txt +++ b/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.kt.txt @@ -14,7 +14,6 @@ class Test1 : IBase { super/*Any*/() /* () */ - .#<$$delegate_0> = i } override fun foo(a: E, b: B) { @@ -34,7 +33,7 @@ class Test1 : IBase { (.#<$$delegate_0>, ).( = ) } - local /* final field */ val <$$delegate_0>: IBase + local /* final field */ val <$$delegate_0>: IBase = i } @@ -43,14 +42,8 @@ class Test2 : IBase { super/*Any*/() /* () */ - .#<$$delegate_0> = j } - var j: IBase - field = j - get - set - override fun foo(a: String, b: B) { .#<$$delegate_0>.foo(a = a, b = b) } @@ -68,7 +61,11 @@ class Test2 : IBase { (.#<$$delegate_0>, ).( = ) } - local /* final field */ val <$$delegate_0>: IBase + local /* final field */ val <$$delegate_0>: IBase = j + var j: IBase + field = j + get + set } diff --git a/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.txt b/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.txt index ccdc5eb4067..0cb00f8c810 100644 --- a/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.txt +++ b/compiler/testData/ir/irText/classes/delegatedGenericImplementation.fir.txt @@ -46,9 +46,6 @@ FILE fqName: fileName:/delegatedGenericImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test1 modality:FINAL visibility:public superTypes:[.IBase.Test1>]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test1> visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Test1.Test1> declared in .Test1' type=.Test1.Test1> origin=null - value: GET_VAR 'i: .IBase.Test1> declared in .Test1.' type=.IBase.Test1> origin=null FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN ($this:.Test1.Test1>, a:E of .Test1, b:B of .Test1.foo) returnType:kotlin.Unit overridden: public abstract fun foo (a: A of .IBase, b: B of .IBase.foo): kotlin.Unit declared in .IBase @@ -109,6 +106,8 @@ FILE fqName: fileName:/delegatedGenericImplementation.kt $receiver: GET_VAR ': kotlin.collections.List.Test1.> declared in .Test1.' type=kotlin.collections.List.Test1.> origin=null : GET_VAR ': D of .Test1.? declared in .Test1.' type=D of .Test1.? origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test1> visibility:local [final] + EXPRESSION_BODY + GET_VAR 'i: .IBase.Test1> declared in .Test1.' type=.IBase.Test1> origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any @@ -129,28 +128,6 @@ FILE fqName: fileName:/delegatedGenericImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test2 modality:FINAL visibility:public superTypes:[.IBase]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Test2 declared in .Test2' type=.Test2 origin=null - value: GET_VAR 'j: .IBase declared in .Test2.' type=.IBase origin=null - PROPERTY name:j visibility:public modality:FINAL [var] - FIELD PROPERTY_BACKING_FIELD name:j type:.IBase visibility:private - EXPRESSION_BODY - GET_VAR 'j: .IBase declared in .Test2.' type=.IBase origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Test2) returnType:.IBase - correspondingProperty: PROPERTY name:j visibility:public modality:FINAL [var] - $this: VALUE_PARAMETER name: type:.Test2 - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): .IBase declared in .Test2' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:j type:.IBase visibility:private' type=.IBase origin=null - receiver: GET_VAR ': .Test2 declared in .Test2.' type=.Test2 origin=null - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Test2, :.IBase) returnType:kotlin.Unit - correspondingProperty: PROPERTY name:j visibility:public modality:FINAL [var] - $this: VALUE_PARAMETER name: type:.Test2 - VALUE_PARAMETER name: index:0 type:.IBase - BLOCK_BODY - SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:j type:.IBase visibility:private' type=kotlin.Unit origin=null - receiver: GET_VAR ': .Test2 declared in .Test2.' type=.Test2 origin=null - value: GET_VAR ': .IBase declared in .Test2.' type=.IBase origin=null FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN ($this:.Test2, a:kotlin.String, b:B of .Test2.foo) returnType:kotlin.Unit overridden: public abstract fun foo (a: A of .IBase, b: B of .IBase.foo): kotlin.Unit declared in .IBase @@ -211,6 +188,27 @@ FILE fqName: fileName:/delegatedGenericImplementation.kt $receiver: GET_VAR ': kotlin.collections.List.Test2.> declared in .Test2.' type=kotlin.collections.List.Test2.> origin=null : GET_VAR ': D of .Test2.? declared in .Test2.' type=D of .Test2.? origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final] + EXPRESSION_BODY + GET_VAR 'j: .IBase declared in .Test2.' type=.IBase origin=null + PROPERTY name:j visibility:public modality:FINAL [var] + FIELD PROPERTY_BACKING_FIELD name:j type:.IBase visibility:private + EXPRESSION_BODY + GET_VAR 'j: .IBase declared in .Test2.' type=.IBase origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Test2) returnType:.IBase + correspondingProperty: PROPERTY name:j visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.Test2 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): .IBase declared in .Test2' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:j type:.IBase visibility:private' type=.IBase origin=null + receiver: GET_VAR ': .Test2 declared in .Test2.' type=.Test2 origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Test2, :.IBase) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:j visibility:public modality:FINAL [var] + $this: VALUE_PARAMETER name: type:.Test2 + VALUE_PARAMETER name: index:0 type:.IBase + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:j type:.IBase visibility:private' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Test2 declared in .Test2.' type=.Test2 origin=null + value: GET_VAR ': .IBase declared in .Test2.' type=.IBase origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/classes/delegatedImplementation.fir.kt.txt b/compiler/testData/ir/irText/classes/delegatedImplementation.fir.kt.txt index 7d3062bf224..32d05a7406b 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementation.fir.kt.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementation.fir.kt.txt @@ -82,7 +82,6 @@ class Test1 : IBase { super/*Any*/() /* () */ - .#<$$delegate_0> = BaseImpl } override fun foo(x: Int, s: String) { @@ -97,7 +96,7 @@ class Test1 : IBase { (.#<$$delegate_0>, ).qux() } - local /* final field */ val <$$delegate_0>: IBase + local /* final field */ val <$$delegate_0>: IBase = BaseImpl } @@ -106,8 +105,6 @@ class Test2 : IBase, IOther { super/*Any*/() /* () */ - .#<$$delegate_0> = BaseImpl - .#<$$delegate_1> = otherImpl(x0 = "", y0 = 42) } override fun foo(x: Int, s: String) { @@ -122,7 +119,7 @@ class Test2 : IBase, IOther { (.#<$$delegate_0>, ).qux() } - local /* final field */ val <$$delegate_0>: IBase + local /* final field */ val <$$delegate_0>: IBase = BaseImpl override val x: String override get(): String { return .#<$$delegate_1>.() @@ -149,7 +146,7 @@ class Test2 : IBase, IOther { (.#<$$delegate_1>, ).( = ) } - local /* final field */ val <$$delegate_1>: IOther + local /* final field */ val <$$delegate_1>: IOther = otherImpl(x0 = "", y0 = 42) } diff --git a/compiler/testData/ir/irText/classes/delegatedImplementation.fir.txt b/compiler/testData/ir/irText/classes/delegatedImplementation.fir.txt index cdb02665cd0..747f419f513 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementation.fir.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementation.fir.txt @@ -200,9 +200,6 @@ FILE fqName: fileName:/delegatedImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test1 modality:FINAL visibility:public superTypes:[.IBase]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Test1 declared in .Test1' type=.Test1 origin=null - value: GET_OBJECT 'CLASS OBJECT name:BaseImpl modality:FINAL visibility:public superTypes:[.IBase]' type=.BaseImpl FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.Test1, x:kotlin.Int, s:kotlin.String) returnType:kotlin.Unit overridden: public abstract fun foo (x: kotlin.Int, s: kotlin.String): kotlin.Unit declared in .IBase @@ -235,6 +232,8 @@ FILE fqName: fileName:/delegatedImplementation.kt receiver: GET_VAR ': .Test1 declared in .Test1.qux' type=.Test1 origin=null $receiver: GET_VAR ': kotlin.String declared in .Test1.qux' type=kotlin.String origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final] + EXPRESSION_BODY + GET_OBJECT 'CLASS OBJECT name:BaseImpl modality:FINAL visibility:public superTypes:[.IBase]' type=.BaseImpl FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any @@ -254,14 +253,6 @@ FILE fqName: fileName:/delegatedImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test2 modality:FINAL visibility:public superTypes:[.IBase; .IOther]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Test2 declared in .Test2' type=.Test2 origin=null - value: GET_OBJECT 'CLASS OBJECT name:BaseImpl modality:FINAL visibility:public superTypes:[.IBase]' type=.BaseImpl - SET_FIELD 'FIELD DELEGATE name:<$$delegate_1> type:.IOther visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Test2 declared in .Test2' type=.Test2 origin=null - value: CALL 'public final fun otherImpl (x0: kotlin.String, y0: kotlin.Int): .IOther declared in ' type=.IOther origin=null - x0: CONST String type=kotlin.String value="" - y0: CONST Int type=kotlin.Int value=42 FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.Test2, x:kotlin.Int, s:kotlin.String) returnType:kotlin.Unit overridden: public abstract fun foo (x: kotlin.Int, s: kotlin.String): kotlin.Unit declared in .IBase @@ -294,6 +285,8 @@ FILE fqName: fileName:/delegatedImplementation.kt receiver: GET_VAR ': .Test2 declared in .Test2.qux' type=.Test2 origin=null $receiver: GET_VAR ': kotlin.String declared in .Test2.qux' type=kotlin.String origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase visibility:local [final] + EXPRESSION_BODY + GET_OBJECT 'CLASS OBJECT name:BaseImpl modality:FINAL visibility:public superTypes:[.IBase]' type=.BaseImpl PROPERTY DELEGATED_MEMBER name:x visibility:public modality:OPEN [val] FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Test2) returnType:kotlin.String correspondingProperty: PROPERTY DELEGATED_MEMBER name:x visibility:public modality:OPEN [val] @@ -367,6 +360,10 @@ FILE fqName: fileName:/delegatedImplementation.kt $receiver: GET_VAR ': kotlin.Byte declared in .Test2.' type=kotlin.Byte origin=null : GET_VAR ': kotlin.Int declared in .Test2.' type=kotlin.Int origin=null FIELD DELEGATE name:<$$delegate_1> type:.IOther visibility:local [final] + EXPRESSION_BODY + CALL 'public final fun otherImpl (x0: kotlin.String, y0: kotlin.Int): .IOther declared in ' type=.IOther origin=null + x0: CONST String type=kotlin.String value="" + y0: CONST Int type=kotlin.Int value=42 FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.kt.txt b/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.kt.txt index f8ae385e192..fb36d5785c8 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.kt.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.kt.txt @@ -3,13 +3,8 @@ class Test : J { super/*Any*/() /* () */ - .#<$$delegate_0> = j } - private val j: J - field = j - private get - override fun takeNotNull(x: @EnhancedNullability String) { .#<$$delegate_0>.takeNotNull(x = x) } @@ -36,7 +31,10 @@ class Test : J { return .#<$$delegate_0>.returnsFlexible() } - local /* final field */ val <$$delegate_0>: J + local /* final field */ val <$$delegate_0>: J = j + private val j: J + field = j + private get } diff --git a/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.txt b/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.txt index 49e7a896708..5cd15a79d17 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementationOfJavaInterface.fir.txt @@ -6,20 +6,6 @@ FILE fqName: fileName:/delegatedImplementationOfJavaInterface.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test modality:FINAL visibility:public superTypes:[.J]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Test declared in .Test' type=.Test origin=null - value: GET_VAR 'j: .J declared in .Test.' type=.J origin=null - PROPERTY name:j visibility:private modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:j type:.J visibility:private [final] - EXPRESSION_BODY - GET_VAR 'j: .J declared in .Test.' type=.J origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.Test) returnType:.J - correspondingProperty: PROPERTY name:j visibility:private modality:FINAL [val] - $this: VALUE_PARAMETER name: type:.Test - BLOCK_BODY - RETURN type=kotlin.Nothing from='private final fun (): .J declared in .Test' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:j type:.J visibility:private [final]' type=.J origin=null - receiver: GET_VAR ': .Test declared in .Test.' type=.Test origin=null FUN DELEGATED_MEMBER name:takeNotNull visibility:public modality:OPEN <> ($this:.Test, x:@[EnhancedNullability] kotlin.String) returnType:kotlin.Unit overridden: public abstract fun takeNotNull (x: @[EnhancedNullability] kotlin.String): kotlin.Unit declared in .J @@ -82,6 +68,19 @@ FILE fqName: fileName:/delegatedImplementationOfJavaInterface.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=.J origin=null receiver: GET_VAR ': .Test declared in .Test.returnsFlexible' type=.Test origin=null FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final] + EXPRESSION_BODY + GET_VAR 'j: .J declared in .Test.' type=.J origin=null + PROPERTY name:j visibility:private modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:j type:.J visibility:private [final] + EXPRESSION_BODY + GET_VAR 'j: .J declared in .Test.' type=.J origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.Test) returnType:.J + correspondingProperty: PROPERTY name:j visibility:private modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Test + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun (): .J declared in .Test' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:j type:.J visibility:private [final]' type=.J origin=null + receiver: GET_VAR ': .Test declared in .Test.' type=.Test origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.kt.txt b/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.kt.txt index 103c62d6993..0c91c731dfd 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.kt.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.kt.txt @@ -24,17 +24,15 @@ class C : IFooBar { super/*Any*/() /* () */ - .#<$$delegate_0> = FooBarImpl - } - - override fun bar() { } override fun foo() { .#<$$delegate_0>.foo() } - local /* final field */ val <$$delegate_0>: IFooBar + local /* final field */ val <$$delegate_0>: IFooBar = FooBarImpl + override fun bar() { + } } diff --git a/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.txt b/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.txt index a30487d58ad..96935a1c251 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.fir.txt @@ -53,14 +53,6 @@ FILE fqName: fileName:/delegatedImplementationWithExplicitOverride.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[.IFooBar]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .C declared in .C' type=.C origin=null - value: GET_OBJECT 'CLASS OBJECT name:FooBarImpl modality:FINAL visibility:public superTypes:[.IFooBar]' type=.FooBarImpl - FUN name:bar visibility:public modality:FINAL <> ($this:.C) returnType:kotlin.Unit - overridden: - public abstract fun bar (): kotlin.Unit declared in .IFooBar - $this: VALUE_PARAMETER name: type:.C - BLOCK_BODY FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.C) returnType:kotlin.Unit overridden: public abstract fun foo (): kotlin.Unit declared in .IFooBar @@ -70,6 +62,13 @@ FILE fqName: fileName:/delegatedImplementationWithExplicitOverride.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final]' type=.IFooBar origin=null receiver: GET_VAR ': .C declared in .C.foo' type=.C origin=null FIELD DELEGATE name:<$$delegate_0> type:.IFooBar visibility:local [final] + EXPRESSION_BODY + GET_OBJECT 'CLASS OBJECT name:FooBarImpl modality:FINAL visibility:public superTypes:[.IFooBar]' type=.FooBarImpl + FUN name:bar visibility:public modality:FINAL <> ($this:.C) returnType:kotlin.Unit + overridden: + public abstract fun bar (): kotlin.Unit declared in .IFooBar + $this: VALUE_PARAMETER name: type:.C + BLOCK_BODY FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.kt.txt b/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.kt.txt index 154bbcaad18..f6da264d0a5 100644 --- a/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.kt.txt +++ b/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.kt.txt @@ -52,14 +52,13 @@ class TestJFoo : IFoo { super/*Any*/() /* () */ - .#<$$delegate_0> = JFoo() } override fun foo(): String { return .#<$$delegate_0>.foo() } - local /* final field */ val <$$delegate_0>: IFoo + local /* final field */ val <$$delegate_0>: IFoo = JFoo() } @@ -68,14 +67,13 @@ class TestK1 : IFoo { super/*Any*/() /* () */ - .#<$$delegate_0> = K1() } override fun foo(): String { return .#<$$delegate_0>.foo() } - local /* final field */ val <$$delegate_0>: IFoo + local /* final field */ val <$$delegate_0>: IFoo = K1() } @@ -84,14 +82,13 @@ class TestK2 : IFoo { super/*Any*/() /* () */ - .#<$$delegate_0> = K2() } override fun foo(): String { return .#<$$delegate_0>.foo() } - local /* final field */ val <$$delegate_0>: IFoo + local /* final field */ val <$$delegate_0>: IFoo = K2() } @@ -100,14 +97,13 @@ class TestK3 : IFoo { super/*Any*/() /* () */ - .#<$$delegate_0> = K3() } override fun foo(): String { return .#<$$delegate_0>.foo() } - local /* final field */ val <$$delegate_0>: IFoo + local /* final field */ val <$$delegate_0>: IFoo = K3() } @@ -116,14 +112,13 @@ class TestK4 : IFoo { super/*Any*/() /* () */ - .#<$$delegate_0> = K4() } override fun foo(): String { return .#<$$delegate_0>.foo() } - local /* final field */ val <$$delegate_0>: IFoo + local /* final field */ val <$$delegate_0>: IFoo = K4() } diff --git a/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt b/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt index cca274e6190..da87507f689 100644 --- a/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt +++ b/compiler/testData/ir/irText/classes/implicitNotNullOnDelegatedImplementation.fir.txt @@ -124,9 +124,6 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:TestJFoo modality:FINAL visibility:public superTypes:[.IFoo]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .TestJFoo declared in .TestJFoo' type=.TestJFoo origin=null - value: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .JFoo' type=.JFoo origin=null FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.TestJFoo) returnType:kotlin.String overridden: public abstract fun foo (): kotlin.String declared in .IFoo @@ -137,6 +134,8 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestJFoo declared in .TestJFoo.foo' type=.TestJFoo origin=null FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + EXPRESSION_BODY + CONSTRUCTOR_CALL 'public constructor () [primary] declared in .JFoo' type=.JFoo origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any @@ -156,9 +155,6 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:TestK1 modality:FINAL visibility:public superTypes:[.IFoo]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .TestK1 declared in .TestK1' type=.TestK1 origin=null - value: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K1' type=.K1 origin=null FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.TestK1) returnType:kotlin.String overridden: public abstract fun foo (): kotlin.String declared in .IFoo @@ -169,6 +165,8 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestK1 declared in .TestK1.foo' type=.TestK1 origin=null FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + EXPRESSION_BODY + CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K1' type=.K1 origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any @@ -188,9 +186,6 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:TestK2 modality:FINAL visibility:public superTypes:[.IFoo]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .TestK2 declared in .TestK2' type=.TestK2 origin=null - value: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K2' type=.K2 origin=null FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.TestK2) returnType:kotlin.String overridden: public abstract fun foo (): kotlin.String declared in .IFoo @@ -201,6 +196,8 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestK2 declared in .TestK2.foo' type=.TestK2 origin=null FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + EXPRESSION_BODY + CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K2' type=.K2 origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any @@ -220,9 +217,6 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:TestK3 modality:FINAL visibility:public superTypes:[.IFoo]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .TestK3 declared in .TestK3' type=.TestK3 origin=null - value: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K3' type=.K3 origin=null FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.TestK3) returnType:kotlin.String overridden: public abstract fun foo (): kotlin.String declared in .IFoo @@ -233,6 +227,8 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestK3 declared in .TestK3.foo' type=.TestK3 origin=null FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + EXPRESSION_BODY + CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K3' type=.K3 origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any @@ -252,9 +248,6 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:TestK4 modality:FINAL visibility:public superTypes:[.IFoo]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .TestK4 declared in .TestK4' type=.TestK4 origin=null - value: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K4' type=.K4 origin=null FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.TestK4) returnType:kotlin.String overridden: public abstract fun foo (): kotlin.String declared in .IFoo @@ -265,6 +258,8 @@ FILE fqName: fileName:/implicitNotNullOnDelegatedImplementation.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=.IFoo origin=null receiver: GET_VAR ': .TestK4 declared in .TestK4.foo' type=.TestK4 origin=null FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + EXPRESSION_BODY + CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K4' type=.K4 origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/declarations/annotations/annotationsOnDelegatedMembers.fir.kt.txt b/compiler/testData/ir/irText/declarations/annotations/annotationsOnDelegatedMembers.fir.kt.txt index d2fd97a09fd..29030292342 100644 --- a/compiler/testData/ir/irText/declarations/annotations/annotationsOnDelegatedMembers.fir.kt.txt +++ b/compiler/testData/ir/irText/declarations/annotations/annotationsOnDelegatedMembers.fir.kt.txt @@ -24,7 +24,6 @@ class DFoo : IFoo { super/*Any*/() /* () */ - .#<$$delegate_0> = d } @Ann @@ -49,7 +48,7 @@ class DFoo : IFoo { return (.#<$$delegate_0>, ).() } - local /* final field */ val <$$delegate_0>: IFoo + local /* final field */ val <$$delegate_0>: IFoo = d } diff --git a/compiler/testData/ir/irText/declarations/annotations/annotationsOnDelegatedMembers.fir.txt b/compiler/testData/ir/irText/declarations/annotations/annotationsOnDelegatedMembers.fir.txt index 6eae326f169..0fc194a84d1 100644 --- a/compiler/testData/ir/irText/declarations/annotations/annotationsOnDelegatedMembers.fir.txt +++ b/compiler/testData/ir/irText/declarations/annotations/annotationsOnDelegatedMembers.fir.txt @@ -59,9 +59,6 @@ FILE fqName: fileName:/annotationsOnDelegatedMembers.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:DFoo modality:FINAL visibility:public superTypes:[.IFoo]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .DFoo declared in .DFoo' type=.DFoo origin=null - value: GET_VAR 'd: .IFoo declared in .DFoo.' type=.IFoo origin=null FUN DELEGATED_MEMBER name:testFun visibility:public modality:OPEN <> ($this:.DFoo) returnType:kotlin.Unit annotations: Ann @@ -113,6 +110,8 @@ FILE fqName: fileName:/annotationsOnDelegatedMembers.kt receiver: GET_VAR ': .DFoo declared in .DFoo.' type=.DFoo origin=null $receiver: GET_VAR ': kotlin.String declared in .DFoo.' type=kotlin.String origin=null FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + EXPRESSION_BODY + GET_VAR 'd: .IFoo declared in .DFoo.' type=.IFoo origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/declarations/annotations/inheritingDeprecation.fir.kt.txt b/compiler/testData/ir/irText/declarations/annotations/inheritingDeprecation.fir.kt.txt index 2c3ee7d7203..9061db9158a 100644 --- a/compiler/testData/ir/irText/declarations/annotations/inheritingDeprecation.fir.kt.txt +++ b/compiler/testData/ir/irText/declarations/annotations/inheritingDeprecation.fir.kt.txt @@ -18,7 +18,6 @@ class Delegated : IFoo { super/*Any*/() /* () */ - .#<$$delegate_0> = foo } @Deprecated(message = "") @@ -33,7 +32,7 @@ class Delegated : IFoo { return (.#<$$delegate_0>, ).() } - local /* final field */ val <$$delegate_0>: IFoo + local /* final field */ val <$$delegate_0>: IFoo = foo } diff --git a/compiler/testData/ir/irText/declarations/annotations/inheritingDeprecation.fir.txt b/compiler/testData/ir/irText/declarations/annotations/inheritingDeprecation.fir.txt index 64901ed4215..ac03ff1228d 100644 --- a/compiler/testData/ir/irText/declarations/annotations/inheritingDeprecation.fir.txt +++ b/compiler/testData/ir/irText/declarations/annotations/inheritingDeprecation.fir.txt @@ -40,9 +40,6 @@ FILE fqName: fileName:/inheritingDeprecation.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Delegated modality:FINAL visibility:public superTypes:[.IFoo]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Delegated declared in .Delegated' type=.Delegated origin=null - value: GET_VAR 'foo: .IFoo declared in .Delegated.' type=.IFoo origin=null PROPERTY DELEGATED_MEMBER name:prop visibility:public modality:OPEN [val] annotations: Deprecated(message = '', replaceWith = , level = ) @@ -72,6 +69,8 @@ FILE fqName: fileName:/inheritingDeprecation.kt receiver: GET_VAR ': .Delegated declared in .Delegated.' type=.Delegated origin=null $receiver: GET_VAR ': kotlin.String declared in .Delegated.' type=kotlin.String origin=null FIELD DELEGATE name:<$$delegate_0> type:.IFoo visibility:local [final] + EXPRESSION_BODY + GET_VAR 'foo: .IFoo declared in .Delegated.' type=.IFoo origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/declarations/kt35550.fir.kt.txt b/compiler/testData/ir/irText/declarations/kt35550.fir.kt.txt index ec35a44d722..90017fc08b0 100644 --- a/compiler/testData/ir/irText/declarations/kt35550.fir.kt.txt +++ b/compiler/testData/ir/irText/declarations/kt35550.fir.kt.txt @@ -11,7 +11,6 @@ class A : I { super/*Any*/() /* () */ - .#<$$delegate_0> = i } override val T.id: T @@ -19,7 +18,7 @@ class A : I { return (.#<$$delegate_0>, ).() } - local /* final field */ val <$$delegate_0>: I + local /* final field */ val <$$delegate_0>: I = i } diff --git a/compiler/testData/ir/irText/declarations/kt35550.fir.txt b/compiler/testData/ir/irText/declarations/kt35550.fir.txt index fca54190d10..d453e82a9ef 100644 --- a/compiler/testData/ir/irText/declarations/kt35550.fir.txt +++ b/compiler/testData/ir/irText/declarations/kt35550.fir.txt @@ -30,9 +30,6 @@ FILE fqName: fileName:/kt35550.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:A modality:FINAL visibility:public superTypes:[.I]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.I visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .A declared in .A' type=.A origin=null - value: GET_VAR 'i: .I declared in .A.' type=.I origin=null PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val] FUN DELEGATED_MEMBER name: visibility:public modality:OPEN ($this:.A, $receiver:T of .A.) returnType:T of .A. correspondingProperty: PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val] @@ -49,6 +46,8 @@ FILE fqName: fileName:/kt35550.kt receiver: GET_VAR ': .A declared in .A.' type=.A origin=null $receiver: GET_VAR ': T of .A. declared in .A.' type=T of .A. origin=null FIELD DELEGATE name:<$$delegate_0> type:.I visibility:local [final] + EXPRESSION_BODY + GET_VAR 'i: .I declared in .A.' type=.I origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.kt.txt b/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.kt.txt index 2ea28d408b8..5a876d4c310 100644 --- a/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.kt.txt +++ b/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.kt.txt @@ -12,7 +12,6 @@ class Test : IBase { super/*Any*/() /* () */ - .#<$$delegate_0> = impl } override fun foo(x: Int) { @@ -28,7 +27,7 @@ class Test : IBase { return .#<$$delegate_0>.() } - local /* final field */ val <$$delegate_0>: IBase + local /* final field */ val <$$delegate_0>: IBase = impl } diff --git a/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.txt b/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.txt index 2e25ff1cdb9..a6077d73000 100644 --- a/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.txt +++ b/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.fir.txt @@ -35,9 +35,6 @@ FILE fqName: fileName:/delegatedMembers.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test modality:FINAL visibility:public superTypes:[.IBase.Test>]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test> visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Test.Test> declared in .Test' type=.Test.Test> origin=null - value: GET_VAR 'impl: .IBase.Test> declared in .Test.' type=.IBase.Test> origin=null FUN DELEGATED_MEMBER name:foo visibility:public modality:OPEN <> ($this:.Test.Test>, x:kotlin.Int) returnType:kotlin.Unit overridden: public abstract fun foo (x: kotlin.Int): kotlin.Unit declared in .IBase @@ -74,6 +71,8 @@ FILE fqName: fileName:/delegatedMembers.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test> visibility:local [final]' type=.IBase.Test> origin=null receiver: GET_VAR ': .Test.Test> declared in .Test.' type=.Test.Test> origin=null FIELD DELEGATE name:<$$delegate_0> type:.IBase.Test> visibility:local [final] + EXPRESSION_BODY + GET_VAR 'impl: .IBase.Test> declared in .Test.' type=.IBase.Test> origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/firProblems/AnnotationLoader.fir.kt.txt b/compiler/testData/ir/irText/firProblems/AnnotationLoader.fir.kt.txt index d5b69b11743..7e96f4877a7 100644 --- a/compiler/testData/ir/irText/firProblems/AnnotationLoader.fir.kt.txt +++ b/compiler/testData/ir/irText/firProblems/AnnotationLoader.fir.kt.txt @@ -56,10 +56,6 @@ class AnnotationLoader { super/*Any*/() /* () */ - .#<$$delegate_0> = visitor - } - - override fun visit() { } override fun visitArray(): Visitor? { @@ -70,7 +66,9 @@ class AnnotationLoader { return .#<$$delegate_0>.visitAnnotation() } - local /* final field */ val <$$delegate_0>: Visitor + local /* final field */ val <$$delegate_0>: Visitor = visitor + override fun visit() { + } } diff --git a/compiler/testData/ir/irText/firProblems/AnnotationLoader.fir.txt b/compiler/testData/ir/irText/firProblems/AnnotationLoader.fir.txt index 4a4e4fe278c..e450d609bc7 100644 --- a/compiler/testData/ir/irText/firProblems/AnnotationLoader.fir.txt +++ b/compiler/testData/ir/irText/firProblems/AnnotationLoader.fir.txt @@ -108,14 +108,6 @@ FILE fqName: fileName:/AnnotationLoader.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name: modality:FINAL visibility:local superTypes:[.Visitor]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Visitor visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .AnnotationLoader.loadAnnotation..visitAnnotation. declared in .AnnotationLoader.loadAnnotation..visitAnnotation.' type=.AnnotationLoader.loadAnnotation..visitAnnotation. origin=null - value: GET_VAR 'val visitor: .Visitor [val] declared in .AnnotationLoader.loadAnnotation..visitAnnotation' type=.Visitor origin=null - FUN name:visit visibility:public modality:FINAL <> ($this:.AnnotationLoader.loadAnnotation..visitAnnotation.) returnType:kotlin.Unit - overridden: - public abstract fun visit (): kotlin.Unit declared in .Visitor - $this: VALUE_PARAMETER name: type:.AnnotationLoader.loadAnnotation..visitAnnotation. - BLOCK_BODY FUN DELEGATED_MEMBER name:visitArray visibility:public modality:OPEN <> ($this:.AnnotationLoader.loadAnnotation..visitAnnotation.) returnType:.Visitor? overridden: public open fun visitArray (): .Visitor? declared in .Visitor @@ -135,6 +127,13 @@ FILE fqName: fileName:/AnnotationLoader.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Visitor visibility:local [final]' type=.Visitor origin=null receiver: GET_VAR ': .AnnotationLoader.loadAnnotation..visitAnnotation. declared in .AnnotationLoader.loadAnnotation..visitAnnotation..visitAnnotation' type=.AnnotationLoader.loadAnnotation..visitAnnotation. origin=null FIELD DELEGATE name:<$$delegate_0> type:.Visitor visibility:local [final] + EXPRESSION_BODY + GET_VAR 'val visitor: .Visitor [val] declared in .AnnotationLoader.loadAnnotation..visitAnnotation' type=.Visitor origin=null + FUN name:visit visibility:public modality:FINAL <> ($this:.AnnotationLoader.loadAnnotation..visitAnnotation.) returnType:kotlin.Unit + overridden: + public abstract fun visit (): kotlin.Unit declared in .Visitor + $this: VALUE_PARAMETER name: type:.AnnotationLoader.loadAnnotation..visitAnnotation. + BLOCK_BODY FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.kt.txt b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.kt.txt index cf7ebc19190..5ae5a47c206 100644 --- a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.kt.txt +++ b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.kt.txt @@ -3,7 +3,6 @@ class Impl : A, B { super/*Any*/() /* () */ - .#<$$delegate_0> = b } override fun add(element: String?): Boolean { @@ -51,7 +50,7 @@ class Impl : A, B { return .#<$$delegate_0>.() } - local /* final field */ val <$$delegate_0>: B + local /* final field */ val <$$delegate_0>: B = b } diff --git a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt index 9c8a43fdf46..6d6bb4ab0cc 100644 --- a/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt +++ b/compiler/testData/ir/irText/firProblems/DelegationAndInheritanceFromJava.fir.txt @@ -6,9 +6,6 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Impl modality:FINAL visibility:public superTypes:[.Foo.A; .Foo.B]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .Impl declared in .Impl' type=.Impl origin=null - value: GET_VAR 'b: .Foo.B declared in .Impl.' type=.Foo.B origin=null FUN DELEGATED_MEMBER name:add visibility:public modality:OPEN <> ($this:.Impl, element:kotlin.String?) returnType:kotlin.Boolean overridden: public abstract fun add (element: E of kotlin.collections.MutableSet): kotlin.Boolean declared in kotlin.collections.MutableSet @@ -124,6 +121,8 @@ FILE fqName: fileName:/DelegationAndInheritanceFromJava.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final]' type=.Foo.B origin=null receiver: GET_VAR ': .Impl declared in .Impl.' type=.Impl origin=null FIELD DELEGATE name:<$$delegate_0> type:.Foo.B visibility:local [final] + EXPRESSION_BODY + GET_VAR 'b: .Foo.B declared in .Impl.' type=.Foo.B origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.fir.kt.txt b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.fir.kt.txt new file mode 100644 index 00000000000..f73b371eb74 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.fir.kt.txt @@ -0,0 +1,66 @@ +class FirSession { + constructor(name: String) /* primary */ { + super/*Any*/() + /* () */ + + } + + val name: String + field = name + get + +} + +interface Fir2IrComponents { + abstract val session: FirSession + abstract get + + abstract val classifierStorage: Fir2IrClassifierStorage + abstract get + +} + +class Fir2IrComponentsStorage : Fir2IrComponents { + constructor(session: FirSession) /* primary */ { + super/*Any*/() + /* () */ + + } + + override val session: FirSession + field = session + override get + + override lateinit var classifierStorage: Fir2IrClassifierStorage + override get + set + +} + +class Fir2IrClassifierStorage : Fir2IrComponents { + constructor(components: Fir2IrComponents) /* primary */ { + super/*Any*/() + /* () */ + + } + + override val session: FirSession + override get(): FirSession { + return .#<$$delegate_0>.() + } + + override val classifierStorage: Fir2IrClassifierStorage + override get(): Fir2IrClassifierStorage { + return .#<$$delegate_0>.() + } + + local /* final field */ val <$$delegate_0>: Fir2IrComponents = components + private val components: Fir2IrComponents + field = components + private get + + private val name: String + field = .().() + private get + +} diff --git a/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.fir.txt b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.fir.txt new file mode 100644 index 00000000000..6ae4fdc9f10 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.fir.txt @@ -0,0 +1,176 @@ +FILE fqName: fileName:/Fir2IrClassifierStorage.kt + CLASS CLASS name:FirSession modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.FirSession + CONSTRUCTOR visibility:public <> (name:kotlin.String) returnType:.FirSession [primary] + VALUE_PARAMETER name:name index:0 type:kotlin.String + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:FirSession modality:FINAL visibility:public superTypes:[kotlin.Any]' + PROPERTY name:name visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final] + EXPRESSION_BODY + GET_VAR 'name: kotlin.String declared in .FirSession.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.FirSession) returnType:kotlin.String + correspondingProperty: PROPERTY name:name visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.FirSession + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in .FirSession' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': .FirSession declared in .FirSession.' type=.FirSession origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS INTERFACE name:Fir2IrComponents modality:ABSTRACT visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Fir2IrComponents + PROPERTY name:session visibility:public modality:ABSTRACT [val] + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:ABSTRACT <> ($this:.Fir2IrComponents) returnType:.FirSession + correspondingProperty: PROPERTY name:session visibility:public modality:ABSTRACT [val] + $this: VALUE_PARAMETER name: type:.Fir2IrComponents + PROPERTY name:classifierStorage visibility:public modality:ABSTRACT [val] + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:ABSTRACT <> ($this:.Fir2IrComponents) returnType:.Fir2IrClassifierStorage + correspondingProperty: PROPERTY name:classifierStorage visibility:public modality:ABSTRACT [val] + $this: VALUE_PARAMETER name: type:.Fir2IrComponents + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Fir2IrComponentsStorage modality:FINAL visibility:public superTypes:[.Fir2IrComponents] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Fir2IrComponentsStorage + CONSTRUCTOR visibility:public <> (session:.FirSession) returnType:.Fir2IrComponentsStorage [primary] + VALUE_PARAMETER name:session index:0 type:.FirSession + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Fir2IrComponentsStorage modality:FINAL visibility:public superTypes:[.Fir2IrComponents]' + PROPERTY name:session visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:session type:.FirSession visibility:private [final] + EXPRESSION_BODY + GET_VAR 'session: .FirSession declared in .Fir2IrComponentsStorage.' type=.FirSession origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Fir2IrComponentsStorage) returnType:.FirSession + correspondingProperty: PROPERTY name:session visibility:public modality:FINAL [val] + overridden: + public abstract fun (): .FirSession declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:.Fir2IrComponentsStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): .FirSession declared in .Fir2IrComponentsStorage' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:session type:.FirSession visibility:private [final]' type=.FirSession origin=null + receiver: GET_VAR ': .Fir2IrComponentsStorage declared in .Fir2IrComponentsStorage.' type=.Fir2IrComponentsStorage origin=null + PROPERTY name:classifierStorage visibility:public modality:FINAL [lateinit,var] + FIELD PROPERTY_BACKING_FIELD name:classifierStorage type:.Fir2IrClassifierStorage visibility:public + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Fir2IrComponentsStorage) returnType:.Fir2IrClassifierStorage + correspondingProperty: PROPERTY name:classifierStorage visibility:public modality:FINAL [lateinit,var] + overridden: + public abstract fun (): .Fir2IrClassifierStorage declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:.Fir2IrComponentsStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): .Fir2IrClassifierStorage declared in .Fir2IrComponentsStorage' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:classifierStorage type:.Fir2IrClassifierStorage visibility:public' type=.Fir2IrClassifierStorage origin=null + receiver: GET_VAR ': .Fir2IrComponentsStorage declared in .Fir2IrComponentsStorage.' type=.Fir2IrComponentsStorage origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Fir2IrComponentsStorage, :.Fir2IrClassifierStorage) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:classifierStorage visibility:public modality:FINAL [lateinit,var] + $this: VALUE_PARAMETER name: type:.Fir2IrComponentsStorage + VALUE_PARAMETER name: index:0 type:.Fir2IrClassifierStorage + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:classifierStorage type:.Fir2IrClassifierStorage visibility:public' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Fir2IrComponentsStorage declared in .Fir2IrComponentsStorage.' type=.Fir2IrComponentsStorage origin=null + value: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrComponentsStorage.' type=.Fir2IrClassifierStorage origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Fir2IrClassifierStorage modality:FINAL visibility:public superTypes:[.Fir2IrComponents] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Fir2IrClassifierStorage + CONSTRUCTOR visibility:public <> (components:.Fir2IrComponents) returnType:.Fir2IrClassifierStorage [primary] + VALUE_PARAMETER name:components index:0 type:.Fir2IrComponents + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Fir2IrClassifierStorage modality:FINAL visibility:public superTypes:[.Fir2IrComponents]' + PROPERTY DELEGATED_MEMBER name:session visibility:public modality:OPEN [val] + FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Fir2IrClassifierStorage) returnType:.FirSession + correspondingProperty: PROPERTY DELEGATED_MEMBER name:session visibility:public modality:OPEN [val] + overridden: + public abstract fun (): .FirSession declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:.Fir2IrClassifierStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun (): .FirSession declared in .Fir2IrClassifierStorage' + CALL 'public abstract fun (): .FirSession declared in .Fir2IrComponents' type=.FirSession origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Fir2IrComponents visibility:local [final]' type=.Fir2IrComponents origin=null + receiver: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage.' type=.Fir2IrClassifierStorage origin=null + PROPERTY DELEGATED_MEMBER name:classifierStorage visibility:public modality:OPEN [val] + FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Fir2IrClassifierStorage) returnType:.Fir2IrClassifierStorage + correspondingProperty: PROPERTY DELEGATED_MEMBER name:classifierStorage visibility:public modality:OPEN [val] + overridden: + public abstract fun (): .Fir2IrClassifierStorage declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:.Fir2IrClassifierStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun (): .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage' + CALL 'public abstract fun (): .Fir2IrClassifierStorage declared in .Fir2IrComponents' type=.Fir2IrClassifierStorage origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Fir2IrComponents visibility:local [final]' type=.Fir2IrComponents origin=null + receiver: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage.' type=.Fir2IrClassifierStorage origin=null + FIELD DELEGATE name:<$$delegate_0> type:.Fir2IrComponents visibility:local [final] + EXPRESSION_BODY + GET_VAR 'components: .Fir2IrComponents declared in .Fir2IrClassifierStorage.' type=.Fir2IrComponents origin=null + PROPERTY name:components visibility:private modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:components type:.Fir2IrComponents visibility:private [final] + EXPRESSION_BODY + GET_VAR 'components: .Fir2IrComponents declared in .Fir2IrClassifierStorage.' type=.Fir2IrComponents origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.Fir2IrClassifierStorage) returnType:.Fir2IrComponents + correspondingProperty: PROPERTY name:components visibility:private modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Fir2IrClassifierStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun (): .Fir2IrComponents declared in .Fir2IrClassifierStorage' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:components type:.Fir2IrComponents visibility:private [final]' type=.Fir2IrComponents origin=null + receiver: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage.' type=.Fir2IrClassifierStorage origin=null + PROPERTY name:name visibility:private modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final] + EXPRESSION_BODY + CALL 'public final fun (): kotlin.String declared in .FirSession' type=kotlin.String origin=GET_PROPERTY + $this: CALL 'public open fun (): .FirSession declared in .Fir2IrClassifierStorage' type=.FirSession origin=GET_PROPERTY + $this: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage' type=.Fir2IrClassifierStorage origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.Fir2IrClassifierStorage) returnType:kotlin.String + correspondingProperty: PROPERTY name:name visibility:private modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Fir2IrClassifierStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun (): kotlin.String declared in .Fir2IrClassifierStorage' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage.' type=.Fir2IrClassifierStorage origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt new file mode 100644 index 00000000000..3fb5b303fdd --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt @@ -0,0 +1,18 @@ +class FirSession(val name: String) + +interface Fir2IrComponents { + val session: FirSession + val classifierStorage: Fir2IrClassifierStorage +} + +class Fir2IrComponentsStorage( + override val session: FirSession +) : Fir2IrComponents { + override lateinit var classifierStorage: Fir2IrClassifierStorage +} + +class Fir2IrClassifierStorage( + private val components: Fir2IrComponents +) : Fir2IrComponents by components { + private val name = session.name +} diff --git a/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt.txt b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt.txt new file mode 100644 index 00000000000..e52d537d945 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt.txt @@ -0,0 +1,65 @@ +class FirSession { + constructor(name: String) /* primary */ { + super/*Any*/() + /* () */ + + } + + val name: String + field = name + get + +} + +interface Fir2IrComponents { + abstract val session: FirSession + abstract get + + abstract val classifierStorage: Fir2IrClassifierStorage + abstract get + +} + +class Fir2IrComponentsStorage : Fir2IrComponents { + constructor(session: FirSession) /* primary */ { + super/*Any*/() + /* () */ + + } + + override val session: FirSession + field = session + override get + + override lateinit var classifierStorage: Fir2IrClassifierStorage + override get + open set + +} + +class Fir2IrClassifierStorage : Fir2IrComponents { + constructor(components: Fir2IrComponents) /* primary */ { + super/*Any*/() + /* () */ + + } + + private val components: Fir2IrComponents + field = components + private get + + override val classifierStorage: Fir2IrClassifierStorage + override get(): Fir2IrClassifierStorage { + return .#components.() + } + + override val session: FirSession + override get(): FirSession { + return .#components.() + } + + private val name: String + field = .().() + private get + +} diff --git a/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.txt b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.txt new file mode 100644 index 00000000000..f33e0eb64c7 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.txt @@ -0,0 +1,173 @@ +FILE fqName: fileName:/Fir2IrClassifierStorage.kt + CLASS CLASS name:FirSession modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.FirSession + CONSTRUCTOR visibility:public <> (name:kotlin.String) returnType:.FirSession [primary] + VALUE_PARAMETER name:name index:0 type:kotlin.String + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:FirSession modality:FINAL visibility:public superTypes:[kotlin.Any]' + PROPERTY name:name visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final] + EXPRESSION_BODY + GET_VAR 'name: kotlin.String declared in .FirSession.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.FirSession) returnType:kotlin.String + correspondingProperty: PROPERTY name:name visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.FirSession + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in .FirSession' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': .FirSession declared in .FirSession.' type=.FirSession origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS INTERFACE name:Fir2IrComponents modality:ABSTRACT visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Fir2IrComponents + PROPERTY name:session visibility:public modality:ABSTRACT [val] + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:ABSTRACT <> ($this:.Fir2IrComponents) returnType:.FirSession + correspondingProperty: PROPERTY name:session visibility:public modality:ABSTRACT [val] + $this: VALUE_PARAMETER name: type:.Fir2IrComponents + PROPERTY name:classifierStorage visibility:public modality:ABSTRACT [val] + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:ABSTRACT <> ($this:.Fir2IrComponents) returnType:.Fir2IrClassifierStorage + correspondingProperty: PROPERTY name:classifierStorage visibility:public modality:ABSTRACT [val] + $this: VALUE_PARAMETER name: type:.Fir2IrComponents + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Fir2IrComponentsStorage modality:FINAL visibility:public superTypes:[.Fir2IrComponents] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Fir2IrComponentsStorage + CONSTRUCTOR visibility:public <> (session:.FirSession) returnType:.Fir2IrComponentsStorage [primary] + VALUE_PARAMETER name:session index:0 type:.FirSession + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Fir2IrComponentsStorage modality:FINAL visibility:public superTypes:[.Fir2IrComponents]' + PROPERTY name:session visibility:public modality:OPEN [val] + FIELD PROPERTY_BACKING_FIELD name:session type:.FirSession visibility:private [final] + EXPRESSION_BODY + GET_VAR 'session: .FirSession declared in .Fir2IrComponentsStorage.' type=.FirSession origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:OPEN <> ($this:.Fir2IrComponentsStorage) returnType:.FirSession + correspondingProperty: PROPERTY name:session visibility:public modality:OPEN [val] + overridden: + public abstract fun (): .FirSession declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:.Fir2IrComponentsStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun (): .FirSession declared in .Fir2IrComponentsStorage' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:session type:.FirSession visibility:private [final]' type=.FirSession origin=null + receiver: GET_VAR ': .Fir2IrComponentsStorage declared in .Fir2IrComponentsStorage.' type=.Fir2IrComponentsStorage origin=null + PROPERTY name:classifierStorage visibility:public modality:OPEN [lateinit,var] + FIELD PROPERTY_BACKING_FIELD name:classifierStorage type:.Fir2IrClassifierStorage visibility:public + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:OPEN <> ($this:.Fir2IrComponentsStorage) returnType:.Fir2IrClassifierStorage + correspondingProperty: PROPERTY name:classifierStorage visibility:public modality:OPEN [lateinit,var] + overridden: + public abstract fun (): .Fir2IrClassifierStorage declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:.Fir2IrComponentsStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun (): .Fir2IrClassifierStorage declared in .Fir2IrComponentsStorage' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:classifierStorage type:.Fir2IrClassifierStorage visibility:public' type=.Fir2IrClassifierStorage origin=null + receiver: GET_VAR ': .Fir2IrComponentsStorage declared in .Fir2IrComponentsStorage.' type=.Fir2IrComponentsStorage origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:OPEN <> ($this:.Fir2IrComponentsStorage, :.Fir2IrClassifierStorage) returnType:kotlin.Unit + correspondingProperty: PROPERTY name:classifierStorage visibility:public modality:OPEN [lateinit,var] + $this: VALUE_PARAMETER name: type:.Fir2IrComponentsStorage + VALUE_PARAMETER name: index:0 type:.Fir2IrClassifierStorage + BLOCK_BODY + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:classifierStorage type:.Fir2IrClassifierStorage visibility:public' type=kotlin.Unit origin=null + receiver: GET_VAR ': .Fir2IrComponentsStorage declared in .Fir2IrComponentsStorage.' type=.Fir2IrComponentsStorage origin=null + value: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrComponentsStorage.' type=.Fir2IrClassifierStorage origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Fir2IrClassifierStorage modality:FINAL visibility:public superTypes:[.Fir2IrComponents] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Fir2IrClassifierStorage + CONSTRUCTOR visibility:public <> (components:.Fir2IrComponents) returnType:.Fir2IrClassifierStorage [primary] + VALUE_PARAMETER name:components index:0 type:.Fir2IrComponents + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Fir2IrClassifierStorage modality:FINAL visibility:public superTypes:[.Fir2IrComponents]' + PROPERTY name:components visibility:private modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:components type:.Fir2IrComponents visibility:private [final] + EXPRESSION_BODY + GET_VAR 'components: .Fir2IrComponents declared in .Fir2IrClassifierStorage.' type=.Fir2IrComponents origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.Fir2IrClassifierStorage) returnType:.Fir2IrComponents + correspondingProperty: PROPERTY name:components visibility:private modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Fir2IrClassifierStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun (): .Fir2IrComponents declared in .Fir2IrClassifierStorage' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:components type:.Fir2IrComponents visibility:private [final]' type=.Fir2IrComponents origin=null + receiver: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage.' type=.Fir2IrClassifierStorage origin=null + PROPERTY DELEGATED_MEMBER name:classifierStorage visibility:public modality:OPEN [val] + FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Fir2IrClassifierStorage) returnType:.Fir2IrClassifierStorage + correspondingProperty: PROPERTY DELEGATED_MEMBER name:classifierStorage visibility:public modality:OPEN [val] + overridden: + public abstract fun (): .Fir2IrClassifierStorage declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:.Fir2IrClassifierStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun (): .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage' + CALL 'public abstract fun (): .Fir2IrClassifierStorage declared in .Fir2IrComponents' type=.Fir2IrClassifierStorage origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:components type:.Fir2IrComponents visibility:private [final]' type=.Fir2IrComponents origin=null + receiver: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage.' type=.Fir2IrClassifierStorage origin=null + PROPERTY DELEGATED_MEMBER name:session visibility:public modality:OPEN [val] + FUN DELEGATED_MEMBER name: visibility:public modality:OPEN <> ($this:.Fir2IrClassifierStorage) returnType:.FirSession + correspondingProperty: PROPERTY DELEGATED_MEMBER name:session visibility:public modality:OPEN [val] + overridden: + public abstract fun (): .FirSession declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:.Fir2IrClassifierStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='public open fun (): .FirSession declared in .Fir2IrClassifierStorage' + CALL 'public abstract fun (): .FirSession declared in .Fir2IrComponents' type=.FirSession origin=null + $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:components type:.Fir2IrComponents visibility:private [final]' type=.Fir2IrComponents origin=null + receiver: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage.' type=.Fir2IrClassifierStorage origin=null + PROPERTY name:name visibility:private modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final] + EXPRESSION_BODY + CALL 'public final fun (): kotlin.String declared in .FirSession' type=kotlin.String origin=GET_PROPERTY + $this: CALL 'public open fun (): .FirSession declared in .Fir2IrClassifierStorage' type=.FirSession origin=GET_PROPERTY + $this: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage' type=.Fir2IrClassifierStorage origin=null + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.Fir2IrClassifierStorage) returnType:kotlin.String + correspondingProperty: PROPERTY name:name visibility:private modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Fir2IrClassifierStorage + BLOCK_BODY + RETURN type=kotlin.Nothing from='private final fun (): kotlin.String declared in .Fir2IrClassifierStorage' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null + receiver: GET_VAR ': .Fir2IrClassifierStorage declared in .Fir2IrClassifierStorage.' type=.Fir2IrClassifierStorage origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .Fir2IrComponents + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/firProblems/SignatureClash.fir.kt.txt b/compiler/testData/ir/irText/firProblems/SignatureClash.fir.kt.txt index 885315add8f..c526daa3155 100644 --- a/compiler/testData/ir/irText/firProblems/SignatureClash.fir.kt.txt +++ b/compiler/testData/ir/irText/firProblems/SignatureClash.fir.kt.txt @@ -34,9 +34,13 @@ data class DataClass : Derived, Delegate { super/*Any*/() /* () */ - .#<$$delegate_0> = delegate } + override fun bar() { + .#<$$delegate_0>.bar() + } + + local /* final field */ val <$$delegate_0>: Delegate = delegate val delegate: Delegate field = delegate get @@ -49,11 +53,6 @@ data class DataClass : Derived, Delegate { return DataClass(delegate = delegate) } - override fun bar() { - .#<$$delegate_0>.bar() - } - - local /* final field */ val <$$delegate_0>: Delegate override fun equals(other: Any?): Boolean { when { EQEQEQ(arg0 = , arg1 = other) -> return true diff --git a/compiler/testData/ir/irText/firProblems/SignatureClash.fir.txt b/compiler/testData/ir/irText/firProblems/SignatureClash.fir.txt index eee7eb43a0e..cb1dbac87ff 100644 --- a/compiler/testData/ir/irText/firProblems/SignatureClash.fir.txt +++ b/compiler/testData/ir/irText/firProblems/SignatureClash.fir.txt @@ -90,9 +90,17 @@ FILE fqName: fileName:/SignatureClash.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:DataClass modality:FINAL visibility:public [data] superTypes:[.Derived; .Delegate]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Delegate visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .DataClass declared in .DataClass' type=.DataClass origin=null - value: GET_VAR 'delegate: .Delegate declared in .DataClass.' type=.Delegate origin=null + FUN DELEGATED_MEMBER name:bar visibility:public modality:OPEN <> ($this:.DataClass) returnType:kotlin.Unit + overridden: + public abstract fun bar (): kotlin.Unit declared in .Delegate + $this: VALUE_PARAMETER name: type:.DataClass + BLOCK_BODY + CALL 'public abstract fun bar (): kotlin.Unit declared in .Delegate' type=kotlin.Unit origin=null + $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Delegate visibility:local [final]' type=.Delegate origin=null + receiver: GET_VAR ': .DataClass declared in .DataClass.bar' type=.DataClass origin=null + FIELD DELEGATE name:<$$delegate_0> type:.Delegate visibility:local [final] + EXPRESSION_BODY + GET_VAR 'delegate: .Delegate declared in .DataClass.' type=.Delegate origin=null PROPERTY name:delegate visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:delegate type:.Delegate visibility:private [final] EXPRESSION_BODY @@ -120,15 +128,6 @@ FILE fqName: fileName:/SignatureClash.kt RETURN type=kotlin.Nothing from='public final fun copy (delegate: .Delegate): .DataClass declared in .DataClass' CONSTRUCTOR_CALL 'public constructor (delegate: .Delegate) [primary] declared in .DataClass' type=.DataClass origin=null delegate: GET_VAR 'delegate: .Delegate declared in .DataClass.copy' type=.Delegate origin=null - FUN DELEGATED_MEMBER name:bar visibility:public modality:OPEN <> ($this:.DataClass) returnType:kotlin.Unit - overridden: - public abstract fun bar (): kotlin.Unit declared in .Delegate - $this: VALUE_PARAMETER name: type:.DataClass - BLOCK_BODY - CALL 'public abstract fun bar (): kotlin.Unit declared in .Delegate' type=kotlin.Unit origin=null - $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.Delegate visibility:local [final]' type=.Delegate origin=null - receiver: GET_VAR ': .DataClass declared in .DataClass.bar' type=.DataClass origin=null - FIELD DELEGATE name:<$$delegate_0> type:.Delegate visibility:local [final] FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:.DataClass, other:kotlin.Any?) returnType:kotlin.Boolean overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/firProblems/kt43342.fir.kt.txt b/compiler/testData/ir/irText/firProblems/kt43342.fir.kt.txt index c8ff8f1c5f3..c11a33034fd 100644 --- a/compiler/testData/ir/irText/firProblems/kt43342.fir.kt.txt +++ b/compiler/testData/ir/irText/firProblems/kt43342.fir.kt.txt @@ -3,13 +3,8 @@ open class ControlFlowInfo : Map { super/*Any*/() /* () */ - .#<$$delegate_0> = map } - val map: Map - field = map - get - override fun containsKey(key: K): Boolean { return .#<$$delegate_0>.containsKey(key = key) } @@ -52,7 +47,10 @@ open class ControlFlowInfo : Map { return .#<$$delegate_0>.() } - local /* final field */ val <$$delegate_0>: Map + local /* final field */ val <$$delegate_0>: Map = map + val map: Map + field = map + get } diff --git a/compiler/testData/ir/irText/firProblems/kt43342.fir.txt b/compiler/testData/ir/irText/firProblems/kt43342.fir.txt index cdd198c1fb4..a5076e5d6e0 100644 --- a/compiler/testData/ir/irText/firProblems/kt43342.fir.txt +++ b/compiler/testData/ir/irText/firProblems/kt43342.fir.txt @@ -8,20 +8,6 @@ FILE fqName: fileName:/kt43342.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:ControlFlowInfo modality:OPEN visibility:public superTypes:[kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo>]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo' type=.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> origin=null - value: GET_VAR 'map: kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo.' type=kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> origin=null - PROPERTY name:map visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> visibility:private [final] - EXPRESSION_BODY - GET_VAR 'map: kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo.' type=kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo>) returnType:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> - correspondingProperty: PROPERTY name:map visibility:public modality:FINAL [val] - $this: VALUE_PARAMETER name: type:.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> visibility:private [final]' type=kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> origin=null - receiver: GET_VAR ': .ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo.' type=.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> origin=null FUN DELEGATED_MEMBER name:containsKey visibility:public modality:OPEN <> ($this:.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo>, key:K of .ControlFlowInfo) returnType:kotlin.Boolean overridden: public abstract fun containsKey (key: K of kotlin.collections.Map): kotlin.Boolean declared in kotlin.collections.Map @@ -125,6 +111,19 @@ FILE fqName: fileName:/kt43342.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> visibility:local [final]' type=kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> origin=null receiver: GET_VAR ': .ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo.' type=.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> origin=null FIELD DELEGATE name:<$$delegate_0> type:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> visibility:local [final] + EXPRESSION_BODY + GET_VAR 'map: kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo.' type=kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> origin=null + PROPERTY name:map visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> visibility:private [final] + EXPRESSION_BODY + GET_VAR 'map: kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo.' type=kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo>) returnType:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> + correspondingProperty: PROPERTY name:map visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> visibility:private [final]' type=kotlin.collections.Map.ControlFlowInfo, V of .ControlFlowInfo> origin=null + receiver: GET_VAR ': .ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> declared in .ControlFlowInfo.' type=.ControlFlowInfo.ControlFlowInfo, V of .ControlFlowInfo> origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/types/javaWildcardType.fir.kt.txt b/compiler/testData/ir/irText/types/javaWildcardType.fir.kt.txt index f497b74edb0..19c032519a3 100644 --- a/compiler/testData/ir/irText/types/javaWildcardType.fir.kt.txt +++ b/compiler/testData/ir/irText/types/javaWildcardType.fir.kt.txt @@ -11,8 +11,6 @@ class C : J, K { super/*Any*/() /* () */ - .#<$$delegate_0> = j - .#<$$delegate_1> = k } override fun jf1(): Collection? { @@ -31,7 +29,7 @@ class C : J, K { .#<$$delegate_0>.jg2(c = c) } - local /* final field */ val <$$delegate_0>: J + local /* final field */ val <$$delegate_0>: J = j override fun kf1(): Collection { return .#<$$delegate_1>.kf1() } @@ -48,7 +46,7 @@ class C : J, K { .#<$$delegate_1>.kg2(c = c) } - local /* final field */ val <$$delegate_1>: K + local /* final field */ val <$$delegate_1>: K = k } diff --git a/compiler/testData/ir/irText/types/javaWildcardType.fir.txt b/compiler/testData/ir/irText/types/javaWildcardType.fir.txt index 256454833dd..eb3ee656b68 100644 --- a/compiler/testData/ir/irText/types/javaWildcardType.fir.txt +++ b/compiler/testData/ir/irText/types/javaWildcardType.fir.txt @@ -32,12 +32,6 @@ FILE fqName: fileName:/javaWildcardType.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[.J; .K]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .C declared in .C' type=.C origin=null - value: GET_VAR 'j: .J declared in .C.' type=.J origin=null - SET_FIELD 'FIELD DELEGATE name:<$$delegate_1> type:.K visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .C declared in .C' type=.C origin=null - value: GET_VAR 'k: .K declared in .C.' type=.K origin=null FUN DELEGATED_MEMBER name:jf1 visibility:public modality:OPEN <> ($this:.C) returnType:kotlin.collections.Collection? overridden: public abstract fun jf1 (): kotlin.collections.Collection? declared in .J @@ -77,6 +71,8 @@ FILE fqName: fileName:/javaWildcardType.kt receiver: GET_VAR ': .C declared in .C.jg2' type=.C origin=null c: GET_VAR 'c: kotlin.collections.Collection? declared in .C.jg2' type=kotlin.collections.Collection? origin=null FIELD DELEGATE name:<$$delegate_0> type:.J visibility:local [final] + EXPRESSION_BODY + GET_VAR 'j: .J declared in .C.' type=.J origin=null FUN DELEGATED_MEMBER name:kf1 visibility:public modality:OPEN <> ($this:.C) returnType:kotlin.collections.Collection overridden: public abstract fun kf1 (): kotlin.collections.Collection declared in .K @@ -116,6 +112,8 @@ FILE fqName: fileName:/javaWildcardType.kt receiver: GET_VAR ': .C declared in .C.kg2' type=.C origin=null c: GET_VAR 'c: kotlin.collections.Collection declared in .C.kg2' type=kotlin.collections.Collection origin=null FIELD DELEGATE name:<$$delegate_1> type:.K visibility:local [final] + EXPRESSION_BODY + GET_VAR 'k: .K declared in .C.' type=.K origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/types/rawTypeInSignature.fir.kt.txt b/compiler/testData/ir/irText/types/rawTypeInSignature.fir.kt.txt index 0c810163b36..0954b249933 100644 --- a/compiler/testData/ir/irText/types/rawTypeInSignature.fir.kt.txt +++ b/compiler/testData/ir/irText/types/rawTypeInSignature.fir.kt.txt @@ -42,7 +42,6 @@ class KRaw : JRaw { super/*Any*/() /* () */ - .#<$$delegate_0> = j } override fun takesRawList(list: List<*>?) { @@ -77,7 +76,7 @@ class KRaw : JRaw { return .#<$$delegate_0>.returnsRawGenericOut() } - local /* final field */ val <$$delegate_0>: JRaw + local /* final field */ val <$$delegate_0>: JRaw = j } diff --git a/compiler/testData/ir/irText/types/rawTypeInSignature.fir.txt b/compiler/testData/ir/irText/types/rawTypeInSignature.fir.txt index 30b0c189dc0..276e36ae09e 100644 --- a/compiler/testData/ir/irText/types/rawTypeInSignature.fir.txt +++ b/compiler/testData/ir/irText/types/rawTypeInSignature.fir.txt @@ -84,9 +84,6 @@ FILE fqName: fileName:/rawTypeInSignature.kt BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:KRaw modality:FINAL visibility:public superTypes:[.JRaw]' - SET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final]' type=kotlin.Unit origin=EQ - receiver: GET_VAR ': .KRaw declared in .KRaw' type=.KRaw origin=null - value: GET_VAR 'j: .JRaw declared in .KRaw.' type=.JRaw origin=null FUN DELEGATED_MEMBER name:takesRawList visibility:public modality:OPEN <> ($this:.KRaw, list:kotlin.collections.List<*>?) returnType:kotlin.Unit overridden: public abstract fun takesRawList (list: kotlin.collections.List<*>?): kotlin.Unit declared in .JRaw @@ -164,6 +161,8 @@ FILE fqName: fileName:/rawTypeInSignature.kt $this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final]' type=.JRaw origin=null receiver: GET_VAR ': .KRaw declared in .KRaw.returnsRawGenericOut' type=.KRaw origin=null FIELD DELEGATE name:<$$delegate_0> type:.JRaw visibility:local [final] + EXPRESSION_BODY + GET_VAR 'j: .JRaw declared in .KRaw.' type=.JRaw origin=null FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index f9d2ebea1ef..87c740b12ff 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -14840,6 +14840,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/fir/FakeOverrideBuilder.kt"); } + @Test + @TestMetadata("Fir2IrClassifierStorage.kt") + public void testFir2IrClassifierStorage() throws Exception { + runTest("compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt"); + } + @Test @TestMetadata("IrBuiltIns.kt") public void testIrBuiltIns() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 42eaa7c9f1c..668138782a5 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -14840,6 +14840,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/fir/FakeOverrideBuilder.kt"); } + @Test + @TestMetadata("Fir2IrClassifierStorage.kt") + public void testFir2IrClassifierStorage() throws Exception { + runTest("compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt"); + } + @Test @TestMetadata("IrBuiltIns.kt") public void testIrBuiltIns() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java index 47055458097..b7324e8531e 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java @@ -2116,6 +2116,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest { runTest("compiler/testData/ir/irText/firProblems/deprecated.kt"); } + @Test + @TestMetadata("Fir2IrClassifierStorage.kt") + public void testFir2IrClassifierStorage() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/Fir2IrClassifierStorage.kt"); + } + @Test @TestMetadata("FirBuilder.kt") public void testFirBuilder() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8b46e23e3fb..0d1479d62d2 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -12273,6 +12273,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/fir/FakeOverrideBuilder.kt"); } + @TestMetadata("Fir2IrClassifierStorage.kt") + public void testFir2IrClassifierStorage() throws Exception { + runTest("compiler/testData/codegen/box/fir/Fir2IrClassifierStorage.kt"); + } + @TestMetadata("IrBuiltIns.kt") public void testIrBuiltIns() throws Exception { runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt"); From 3e17317f316c260785ef1737542ece4fac6672d3 Mon Sep 17 00:00:00 2001 From: Muhammad Hakim Asy'ari Date: Mon, 8 Feb 2021 20:41:38 +0700 Subject: [PATCH 019/153] Update steps to install JDK 6 on Mac OS (#4052) --- ReadMe.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 8168a57e163..3649308040a 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -59,8 +59,8 @@ You also can use [Gradle properties](https://docs.gradle.org/current/userguide/b Note: The JDK 6 for MacOS is not available on Oracle's site. You can install it by ```bash -$ brew tap caskroom/versions -$ brew cask install java6 +$ brew tap homebrew/cask-versions +$ brew install --cask java6 ``` On Windows you might need to add long paths setting to the repo: From 872effc21ef7855b9a21032806827516ed71514e Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Mon, 8 Feb 2021 14:21:05 +0100 Subject: [PATCH 020/153] Check declaration modifier for actual method to avoid freeze Checking modifier aims to get rid of unnecessary resolve for methods in non MPP (the most) cases Relates to #KTIJ-1200 --- .../src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt index ab72f0c2e7c..2a0b20173dd 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinIconProvider.kt @@ -7,7 +7,8 @@ package org.jetbrains.kotlin.idea import org.jetbrains.kotlin.idea.util.hasMatchingExpected import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier class KotlinIconProvider : KotlinIconProviderBase() { - override fun KtDeclaration.isMatchingExpected() = hasMatchingExpected() + override fun KtDeclaration.isMatchingExpected() = hasActualModifier() && hasMatchingExpected() } \ No newline at end of file From d96921e287321ac549317ddba97b1325a78cf6b4 Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 5 Feb 2021 13:48:26 +0100 Subject: [PATCH 021/153] FIR2IR: collect annotations when expanding type aliases --- .../kotlin/fir/backend/ConversionUtils.kt | 10 ++++++---- .../kotlin/fir/backend/Fir2IrTypeConverter.kt | 14 ++++++++------ .../codegen/FirBlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/box/typealias/extensionFunction.kt | 8 ++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/IrBlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/LightAnalysisModeTestGenerated.java | 5 +++++ .../semantics/IrJsCodegenBoxES6TestGenerated.java | 5 +++++ .../ir/semantics/IrJsCodegenBoxTestGenerated.java | 5 +++++ .../test/semantics/JsCodegenBoxTestGenerated.java | 5 +++++ .../semantics/IrCodegenBoxWasmTestGenerated.java | 5 +++++ 11 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 compiler/testData/codegen/box/typealias/extensionFunction.kt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index e7ee5d59922..75c26fb8444 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty +import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference @@ -86,16 +87,17 @@ class ConversionTypeContext internal constructor( fun FirClassifierSymbol<*>.toSymbol( session: FirSession, classifierStorage: Fir2IrClassifierStorage, - typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT, + handleAnnotations: ((List) -> Unit)? = null ): IrClassifierSymbol { return when (this) { is FirTypeParameterSymbol -> { classifierStorage.getIrTypeParameterSymbol(this, typeContext) } is FirTypeAliasSymbol -> { - val typeAlias = fir - val coneClassLikeType = typeAlias.expandedTypeRef.coneType as ConeClassLikeType - coneClassLikeType.lookupTag.toSymbol(session)!!.toSymbol(session, classifierStorage) + handleAnnotations?.invoke(fir.expandedTypeRef.annotations) + val coneClassLikeType = fir.expandedTypeRef.coneType as ConeClassLikeType + coneClassLikeType.lookupTag.toSymbol(session)!!.toSymbol(session, classifierStorage, typeContext, handleAnnotations) } is FirClassSymbol -> { classifierStorage.getIrClassSymbol(this) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt index 688e77225cd..18138333a5e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.expressions.classId import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.StandardClassIds +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.* import org.jetbrains.kotlin.ir.expressions.IrConstructorCall @@ -19,6 +20,7 @@ import org.jetbrains.kotlin.ir.types.IrTypeArgument import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.Variance @@ -84,13 +86,13 @@ class Fir2IrTypeConverter( return when (this) { is ConeKotlinErrorType -> createErrorType() is ConeLookupTagBasedType -> { - val classId = this.classId - val irSymbol = getBuiltInClassSymbol(classId) ?: run { - val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType() - firSymbol.toSymbol(session, classifierStorage, typeContext) - } - val typeAnnotations: MutableList = mutableListOf() + val typeAnnotations = mutableListOf() typeAnnotations += with(annotationGenerator) { annotations.toIrAnnotations() } + val irSymbol = getBuiltInClassSymbol(classId) + ?: lookupTag.toSymbol(session)?.toSymbol(session, classifierStorage, typeContext) { + typeAnnotations += with(annotationGenerator) { it.toIrAnnotations() } + } + ?: return createErrorType() if (hasEnhancedNullability) { builtIns.enhancedNullabilityAnnotationConstructorCall()?.let { typeAnnotations += it diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 2bea9176c2b..b878b930906 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -38772,6 +38772,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt"); } + @Test + @TestMetadata("extensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("compiler/testData/codegen/box/typealias/extensionFunction.kt"); + } + @Test @TestMetadata("genericTypeAliasConstructor.kt") public void testGenericTypeAliasConstructor() throws Exception { diff --git a/compiler/testData/codegen/box/typealias/extensionFunction.kt b/compiler/testData/codegen/box/typealias/extensionFunction.kt new file mode 100644 index 00000000000..7c1bda54df3 --- /dev/null +++ b/compiler/testData/codegen/box/typealias/extensionFunction.kt @@ -0,0 +1,8 @@ +typealias F = T.() -> R + +inline fun T.myRun(f: F) = f() + +fun box(): String { + val x = "K" + return "O".myRun { this + x } +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 87c740b12ff..78043e67679 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -38978,6 +38978,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt"); } + @Test + @TestMetadata("extensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("compiler/testData/codegen/box/typealias/extensionFunction.kt"); + } + @Test @TestMetadata("genericTypeAliasConstructor.kt") public void testGenericTypeAliasConstructor() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 668138782a5..6ec08af0bff 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -38772,6 +38772,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt"); } + @Test + @TestMetadata("extensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("compiler/testData/codegen/box/typealias/extensionFunction.kt"); + } + @Test @TestMetadata("genericTypeAliasConstructor.kt") public void testGenericTypeAliasConstructor() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 0d1479d62d2..c3af176732e 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -31333,6 +31333,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt"); } + @TestMetadata("extensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("compiler/testData/codegen/box/typealias/extensionFunction.kt"); + } + @TestMetadata("genericTypeAliasConstructor.kt") public void testGenericTypeAliasConstructor() throws Exception { runTest("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 610047dfa2a..791de4bd8af 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -26734,6 +26734,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt"); } + @TestMetadata("extensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("compiler/testData/codegen/box/typealias/extensionFunction.kt"); + } + @TestMetadata("genericTypeAliasConstructor.kt") public void testGenericTypeAliasConstructor() throws Exception { runTest("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 5ee340ea5bb..9a1556f7db5 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -26219,6 +26219,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt"); } + @TestMetadata("extensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("compiler/testData/codegen/box/typealias/extensionFunction.kt"); + } + @TestMetadata("genericTypeAliasConstructor.kt") public void testGenericTypeAliasConstructor() throws Exception { runTest("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 0011f4a413b..44ef736c75e 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -26184,6 +26184,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt"); } + @TestMetadata("extensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("compiler/testData/codegen/box/typealias/extensionFunction.kt"); + } + @TestMetadata("genericTypeAliasConstructor.kt") public void testGenericTypeAliasConstructor() throws Exception { runTest("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 6d2b6c862c2..77f4dddc959 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -14490,6 +14490,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt"); } + @TestMetadata("extensionFunction.kt") + public void testExtensionFunction() throws Exception { + runTest("compiler/testData/codegen/box/typealias/extensionFunction.kt"); + } + @TestMetadata("genericTypeAliasConstructor.kt") public void testGenericTypeAliasConstructor() throws Exception { runTest("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt"); From 4a381d4b83699eaca13268f46152926921d4f966 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 5 Feb 2021 12:34:20 +0300 Subject: [PATCH 022/153] FIR DFA: update receivers properly in case of single flow in merge point --- .../FirBlackBoxCodegenTestGenerated.java | 6 +++ .../PersistentImplicitReceiverStack.kt | 2 +- .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 27 +++++++++---- .../fir/resolve/dfa/PersistentLogicSystem.kt | 3 -- .../testData/codegen/box/fir/LookupTags.kt | 39 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ 8 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/codegen/box/fir/LookupTags.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index b878b930906..7f21b3dbeda 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -14852,6 +14852,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt"); } + @Test + @TestMetadata("LookupTags.kt") + public void testLookupTags() throws Exception { + runTest("compiler/testData/codegen/box/fir/LookupTags.kt"); + } + @Test @TestMetadata("NameHighlighter.kt") public void testNameHighlighter() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt index b449cc0a153..d7be8b91e7d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/PersistentImplicitReceiverStack.kt @@ -37,7 +37,7 @@ class PersistentImplicitReceiverStack private constructor( fun add(name: Name?, value: ImplicitReceiverValue<*>): PersistentImplicitReceiverStack { val stack = stack.add(value) - val originalTypes = originalTypes.add(value.type) + val originalTypes = originalTypes.add(value.originalType) val index = stack.size - 1 val indexesPerLabel = name?.let { indexesPerLabel.put(it, index) } ?: indexesPerLabel val indexesPerSymbol = indexesPerSymbol.put(value.boundSymbol, index) 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 6d3b14621f3..e9e965b1d18 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 @@ -582,7 +582,7 @@ abstract class FirDataFlowAnalyzer( syntheticElseNode.mergeIncomingFlow() } } - whenExitNode.mergeIncomingFlow(updateReceivers = true) + whenExitNode.mergeIncomingFlow() } // ----------------------------------- While Loop ----------------------------------- @@ -675,7 +675,7 @@ abstract class FirDataFlowAnalyzer( fun enterFinallyBlock() { // NB: fork to isolate effects inside the finally block // Otherwise, changes in the finally block could affect the previous nodes: try main block and catch clauses. - graphBuilder.enterFinallyBlock().mergeIncomingFlow(shouldForkFlow = true) + graphBuilder.enterFinallyBlock().mergeIncomingFlow(updateReceivers = true, shouldForkFlow = true) } fun exitFinallyBlock(tryExpression: FirTryExpression) { @@ -1144,15 +1144,28 @@ abstract class FirDataFlowAnalyzer( private val CFGNode<*>.origin: CFGNode<*> get() = if (this is StubNode) firstPreviousNode else this private fun > T.mergeIncomingFlow( + // This flag should be set true if we're changing flow branches from one to another (e.g. in when, try->catch) updateReceivers: Boolean = false, shouldForkFlow: Boolean = false ): T = this.also { node -> - val previousFlows = if (node.isDead) - node.previousNodes.mapNotNull { runIf(!node.incomingEdges.getValue(it).kind.isBack) { it.flow } } - else - node.previousNodes.mapNotNull { prev -> prev.takeIf { node.incomingEdges.getValue(it).kind.usedInDfa }?.flow } + val previousFlows = mutableListOf() + var deadForwardCount = 0 + for (previousNode in previousNodes) { + val incomingEdgeKind = node.incomingEdges.getValue(previousNode).kind + if (node.isDead) { + if (!incomingEdgeKind.isBack) { + previousFlows += previousNode.flow + } + } else if (incomingEdgeKind.usedInDfa) { + previousFlows += previousNode.flow + } + if (incomingEdgeKind == EdgeKind.DeadForward) { + deadForwardCount++ + } + } var flow = logicSystem.joinFlow(previousFlows) - if (updateReceivers) { + // deadForwardCount should be added due to cases like merge after 'if (...) return else ...' + if (updateReceivers || previousFlows.size + deadForwardCount > 1) { logicSystem.updateAllReceivers(flow) } if (shouldForkFlow) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt index 567f9226ffa..61aaa618a76 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PersistentLogicSystem.kt @@ -138,9 +138,6 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste } commonFlow.addVariableAliases(aliasedVariablesThatDontChangeAlias) - - updateAllReceivers(commonFlow) - return commonFlow } diff --git a/compiler/testData/codegen/box/fir/LookupTags.kt b/compiler/testData/codegen/box/fir/LookupTags.kt new file mode 100644 index 00000000000..4a22d1e8754 --- /dev/null +++ b/compiler/testData/codegen/box/fir/LookupTags.kt @@ -0,0 +1,39 @@ +// TARGET_BACKEND: JVM + +abstract class ConeClassLikeLookupTag { + abstract val status: String +} + +class ConeClassLikeLookupTagImpl : ConeClassLikeLookupTag() { + override var status: String = "" + private set + + fun change(newStatus: String) { + status = newStatus + } +} + +class ConeClassLikeErrorLookupTag : ConeClassLikeLookupTag() { + override val status: String + get() = "ERROR" +} + +fun ConeClassLikeLookupTag.foo(): String { + (this as? ConeClassLikeLookupTagImpl)?.status?.takeIf { it == "OK" }?.let { return it } + return status.also { + (this as? ConeClassLikeLookupTagImpl)?.bar(it) + } +} + +fun ConeClassLikeLookupTagImpl.bar(s: String) { + change(s) +} + +fun box(): String { + val tag = ConeClassLikeErrorLookupTag() + tag.foo() + val tag2 = ConeClassLikeLookupTagImpl() + tag2.change("OK") + tag2.foo() + return tag2.status +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 78043e67679..4fabe55fdda 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -14852,6 +14852,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt"); } + @Test + @TestMetadata("LookupTags.kt") + public void testLookupTags() throws Exception { + runTest("compiler/testData/codegen/box/fir/LookupTags.kt"); + } + @Test @TestMetadata("NameHighlighter.kt") public void testNameHighlighter() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 6ec08af0bff..32b9bcdcee2 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -14852,6 +14852,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt"); } + @Test + @TestMetadata("LookupTags.kt") + public void testLookupTags() throws Exception { + runTest("compiler/testData/codegen/box/fir/LookupTags.kt"); + } + @Test @TestMetadata("NameHighlighter.kt") public void testNameHighlighter() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index c3af176732e..f89ad546ddd 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -12283,6 +12283,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/fir/IrBuiltIns.kt"); } + @TestMetadata("LookupTags.kt") + public void testLookupTags() throws Exception { + runTest("compiler/testData/codegen/box/fir/LookupTags.kt"); + } + @TestMetadata("NameHighlighter.kt") public void testNameHighlighter() throws Exception { runTest("compiler/testData/codegen/box/fir/NameHighlighter.kt"); From 2a46da906cc3eb95d9968c55b102f7e1634151d0 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Thu, 4 Feb 2021 20:46:49 +0300 Subject: [PATCH 023/153] Provide additional information about missing supertypes Add -X flag to report extra compiler diagnostics which migth break compatibility. Use the flag to unconditionally check constructors without fear of prematurely evaluating lazy supertypes. KT-19234 KT-42404 KT-44583 --- .../arguments/CommonCompilerArguments.kt | 11 ++++++++ .../messages/AnalyzerWithCompilerReport.kt | 4 +++ .../MissingDependencySupertypeChecker.kt | 7 ++++- compiler/testData/cli/js/jsExtraHelp.out | 2 ++ compiler/testData/cli/jvm/extraHelp.out | 2 ++ .../output.txt | 1 + .../incompleteHierarchyInJava/output.txt | 1 + .../incompleteHierarchyInKotlin/output.txt | 1 + .../output.txt | 1 + .../output.txt | 1 + .../library/test/Sub.java | 5 ++++ .../library/test/SubKt.kt | 11 ++++++++ .../library/test/Super.java | 7 +++++ .../output.txt | 20 ++++++++++++++ .../source.kt | 26 +++++++++++++++++++ .../CompileKotlinAgainstCustomBinariesTest.kt | 8 ++++++ .../kotlin/config/LanguageVersionSettings.kt | 2 ++ 17 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/Sub.java create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/SubKt.kt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/Super.java create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/output.txt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt index d56f5fc657c..7efdb25c84e 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt @@ -357,6 +357,13 @@ abstract class CommonCompilerArguments : CommonToolArguments() { ) var suppressVersionWarnings: Boolean by FreezableVar(false) + @Argument( + value = "-Xextended-compiler-checks", + description = "Enable additional compiler checks that might provide verbose diagnostic information for certain errors.\n" + + "Warning: this mode is not backward-compatible and might cause compilation errors in previously compiled code." + ) + var extendedCompilerChecks: Boolean by FreezableVar(false) + open fun configureAnalysisFlags(collector: MessageCollector): MutableMap, Any> { return HashMap, Any>().apply { put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck) @@ -424,6 +431,10 @@ abstract class CommonCompilerArguments : CommonToolArguments() { put(LanguageFeature.InferenceCompatibility, LanguageFeature.State.ENABLED) } + if (extendedCompilerChecks) { + put(LanguageFeature.ExtendedCompilerChecks, LanguageFeature.State.ENABLED) + } + if (progressiveMode) { LanguageFeature.values().filter { it.kind.enabledInProgressiveMode }.forEach { // Don't overwrite other settings: users may want to turn off some particular diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt index d5e0db6b644..730a5558bd7 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* import org.jetbrains.kotlin.codegen.state.IncompatibleClassTrackerImpl import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.diagnostics.* @@ -72,6 +73,9 @@ class AnalyzerWithCompilerReport( .append(", unresolved supertypes: ").append(unresolved!!.joinToString()) .append("\n") } + if (!languageVersionSettings.supportsFeature(LanguageFeature.ExtendedCompilerChecks)) { + message.append("Adding -Xextended-compiler-checks argument might provide additional information.\n") + } messageCollector.report(ERROR, message.toString()) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt index cd5c71e2d89..7ea1aa45dcd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.resolve.checkers import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.KtDeclaration @@ -48,7 +49,11 @@ object MissingDependencySupertypeChecker { descriptor.dispatchReceiverParameter?.declaration, reportOn, context.trace, context.missingSupertypesResolver ) - if (descriptor !is ConstructorDescriptor && descriptor !is FakeCallableDescriptorForObject && !errorReported) { + + val eagerChecksAllowed = context.languageVersionSettings.supportsFeature(LanguageFeature.ExtendedCompilerChecks) + val unresolvedLazySupertypesByDefault = descriptor is ConstructorDescriptor || descriptor is FakeCallableDescriptorForObject + + if (eagerChecksAllowed || !unresolvedLazySupertypesByDefault && !errorReported) { // The constructed class' own supertypes are not resolved after constructor call, // so its containing declaration should not be checked. // Dispatch receiver is checked before for case of inner class constructor call. diff --git a/compiler/testData/cli/js/jsExtraHelp.out b/compiler/testData/cli/js/jsExtraHelp.out index 766636dd930..b6134d27332 100644 --- a/compiler/testData/cli/js/jsExtraHelp.out +++ b/compiler/testData/cli/js/jsExtraHelp.out @@ -44,6 +44,8 @@ where advanced options include: -Xexplicit-api={strict|warning|disable} Force compiler to report errors on all public API declarations without explicit visibility or return type. Use 'warning' level to issue warnings instead of errors. + -Xextended-compiler-checks Enable additional compiler checks that might provide verbose diagnostic information for certain errors. + Warning: this mode is not backward-compatible and might cause compilation errors in previously compiled code. -Xinference-compatibility Enable compatibility changes for generic type inference algorithm -Xinline-classes Enable experimental inline classes -Xintellij-plugin-root= Path to the kotlin-compiler.jar or directory where IntelliJ configuration files can be found diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index 8c5061724e1..374d9ca8499 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -152,6 +152,8 @@ where advanced options include: -Xexplicit-api={strict|warning|disable} Force compiler to report errors on all public API declarations without explicit visibility or return type. Use 'warning' level to issue warnings instead of errors. + -Xextended-compiler-checks Enable additional compiler checks that might provide verbose diagnostic information for certain errors. + Warning: this mode is not backward-compatible and might cause compilation errors in previously compiled code. -Xinference-compatibility Enable compatibility changes for generic type inference algorithm -Xinline-classes Enable experimental inline classes -Xintellij-plugin-root= Path to the kotlin-compiler.jar or directory where IntelliJ configuration files can be found diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyErrorPositions/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyErrorPositions/output.txt index 98c12b14fef..ea5ffd56f74 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyErrorPositions/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyErrorPositions/output.txt @@ -1,5 +1,6 @@ error: supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath: class test.Sub, unresolved supertypes: test.Super +Adding -Xextended-compiler-checks argument might provide additional information. compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyErrorPositions/source.kt:3:1: error: cannot access 'test.Super' which is a supertype of 'SubSub'. Check your module classpath for missing or conflicting dependencies class SubSub : Sub() diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInJava/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInJava/output.txt index c92ccf9dfb0..5c1236ca777 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInJava/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInJava/output.txt @@ -1,5 +1,6 @@ error: supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath: class test.Sub, unresolved supertypes: test.Super +Adding -Xextended-compiler-checks argument might provide additional information. compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInJava/source.kt:3:1: error: cannot access 'test.Super' which is a supertype of 'SubSub'. Check your module classpath for missing or conflicting dependencies class SubSub : Sub() diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInKotlin/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInKotlin/output.txt index faeca3c57dc..8171f0c3fed 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInKotlin/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInKotlin/output.txt @@ -1,5 +1,6 @@ error: supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath: class test.Sub, unresolved supertypes: test.Super +Adding -Xextended-compiler-checks argument might provide additional information. compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyInKotlin/source.kt:3:1: error: cannot access 'test.Super' which is a supertype of 'SubSub'. Check your module classpath for missing or conflicting dependencies class SubSub : Sub() diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyMissingInterface/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyMissingInterface/output.txt index 71b5795f63e..29fad2bbc02 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyMissingInterface/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyMissingInterface/output.txt @@ -1,5 +1,6 @@ error: supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath: class test.B, unresolved supertypes: test.A +Adding -Xextended-compiler-checks argument might provide additional information. compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyMissingInterface/source.kt:5:15: error: cannot access 'test.A' which is a supertype of 'test.B'. Check your module classpath for missing or conflicting dependencies D.m(B.n()) diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyOfEnclosingClass/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyOfEnclosingClass/output.txt index 0c1c50f7b34..c6a2ae58a40 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyOfEnclosingClass/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyOfEnclosingClass/output.txt @@ -1,6 +1,7 @@ error: supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath: class test.SubClass, unresolved supertypes: test.Super class test.SubObject, unresolved supertypes: test.Super +Adding -Xextended-compiler-checks argument might provide additional information. compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyOfEnclosingClass/source.kt:6:16: error: cannot access 'test.Super' which is a supertype of 'test.SubClass'. Check your module classpath for missing or conflicting dependencies SubClass().Inner() // Error - dispatch receiver misses supertype diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/Sub.java b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/Sub.java new file mode 100644 index 00000000000..aa08b2fb540 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/Sub.java @@ -0,0 +1,5 @@ +package test; + +public class Sub extends Super { + +} \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/SubKt.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/SubKt.kt new file mode 100644 index 00000000000..e14b52fe04f --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/SubKt.kt @@ -0,0 +1,11 @@ +package test + +class SubKt : Super() { + companion object { + fun companionMethod() = "OK" + } + + object InnerObject { + fun objectMethod() = "OK" + } +} \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/Super.java b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/Super.java new file mode 100644 index 00000000000..56493e0dee6 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/library/test/Super.java @@ -0,0 +1,7 @@ +package test; + +public class Super { + String foo() { + return "Super"; + } +} \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/output.txt new file mode 100644 index 00000000000..2ff691d93aa --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/output.txt @@ -0,0 +1,20 @@ +error: supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath: + class test.Sub, unresolved supertypes: test.Super + class test.SubKt, unresolved supertypes: test.Super + +compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt:12:32: error: cannot access 'test.Super' which is a supertype of 'Sub'. Check your module classpath for missing or conflicting dependencies +fun simpleFun(arg: Sub): Sub = Sub() + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt:19:18: error: cannot access 'test.Super' which is a supertype of 'Sub'. Check your module classpath for missing or conflicting dependencies + val x: Sub = Sub() + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt:21:18: error: cannot access 'test.Super' which is a supertype of 'Sub'. Check your module classpath for missing or conflicting dependencies + useCallRef(::Sub) + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt:22:15: error: cannot access 'test.Super' which is a supertype of 'Sub'. Check your module classpath for missing or conflicting dependencies + simpleFun(Sub()) + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt:23:20: error: cannot access 'test.Super' which is a supertype of 'Sub'. Check your module classpath for missing or conflicting dependencies + inlineFun(Sub()) + ^ +COMPILATION_ERROR diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt new file mode 100644 index 00000000000..d68fac51dae --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/incompleteHierarchyWithExtendedCompilerChecks/source.kt @@ -0,0 +1,26 @@ +import test.Sub as MySub +import test.SubKt + +typealias Sub = MySub + +class Test + +@Suppress("UNUSED_PARAMETER") +fun useCallRef(ref: Any?) {} + +@Suppress("UNUSED_PARAMETER") +fun simpleFun(arg: Sub): Sub = Sub() + +inline fun inlineFun(t: T) = t + +// In conservative mode without -Xextended-compiler-checks flag these usages don't cause compilation error +fun test() { + @Suppress("UNUSED_VARIABLE") + val x: Sub = Sub() + Test() + useCallRef(::Sub) + simpleFun(Sub()) + inlineFun(Sub()) + SubKt.companionMethod() + SubKt.InnerObject.objectMethod() +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index c36330550c9..8b4940a5851 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -229,6 +229,14 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration doTestBrokenLibrary("library", "test/Super.class") } + fun testIncompleteHierarchyWithExtendedCompilerChecks() { + doTestBrokenLibrary( + "library", + "test/Super.class", + additionalOptions = listOf("-Xextended-compiler-checks"), + ) + } + fun testIncompleteHierarchyErrorPositions() { doTestBrokenLibrary("library", "test/Super.class") } diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 1fd27a05cc3..e7eff53f676 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -168,6 +168,8 @@ enum class LanguageFeature( // Looks like we can't enable it until KT-26245 is fixed because otherwise some use cases become broken because of overrides ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated(sinceVersion = null, kind = BUG_FIX), + ExtendedCompilerChecks(sinceVersion = null), + // Experimental features Coroutines( From 75954dd1a45a5ebccb6ee7216e0609d4a7e5ecc2 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Mon, 8 Feb 2021 15:29:45 +0300 Subject: [PATCH 024/153] Minor: refactor extended compiler checks Use an analysis flag instead of a stub language feature --- .../kotlin/cli/common/arguments/CommonCompilerArguments.kt | 5 +---- .../kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt | 4 ++-- .../config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt | 3 +++ .../resolve/checkers/MissingDependencySupertypeChecker.kt | 3 ++- .../org/jetbrains/kotlin/config/LanguageVersionSettings.kt | 2 -- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt index 7efdb25c84e..9dc44f27ab8 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt @@ -382,6 +382,7 @@ abstract class CommonCompilerArguments : CommonToolArguments() { CompilerMessageSeverity.ERROR, "Unknown value for parameter -Xexplicit-api: '$explicitApi'. Value should be one of ${ExplicitApiMode.availableValues()}" ) + put(AnalysisFlags.extendedCompilerChecks, extendedCompilerChecks) } } @@ -431,10 +432,6 @@ abstract class CommonCompilerArguments : CommonToolArguments() { put(LanguageFeature.InferenceCompatibility, LanguageFeature.State.ENABLED) } - if (extendedCompilerChecks) { - put(LanguageFeature.ExtendedCompilerChecks, LanguageFeature.State.ENABLED) - } - if (progressiveMode) { LanguageFeature.values().filter { it.kind.enabledInProgressiveMode }.forEach { // Don't overwrite other settings: users may want to turn off some particular diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt index 730a5558bd7..74a026062a7 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt @@ -25,8 +25,8 @@ import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* import org.jetbrains.kotlin.codegen.state.IncompatibleClassTrackerImpl +import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.diagnostics.* @@ -73,7 +73,7 @@ class AnalyzerWithCompilerReport( .append(", unresolved supertypes: ").append(unresolved!!.joinToString()) .append("\n") } - if (!languageVersionSettings.supportsFeature(LanguageFeature.ExtendedCompilerChecks)) { + if (!languageVersionSettings.getFlag(AnalysisFlags.extendedCompilerChecks)) { message.append("Adding -Xextended-compiler-checks argument might provide additional information.\n") } messageCollector.report(ERROR, message.toString()) diff --git a/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt b/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt index 3cab8a5ff3a..00e02de39e0 100644 --- a/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt +++ b/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt @@ -50,4 +50,7 @@ object AnalysisFlags { @JvmStatic val libraryToSourceAnalysis by AnalysisFlag.Delegates.Boolean + + @JvmStatic + val extendedCompilerChecks by AnalysisFlag.Delegates.Boolean } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt index 7ea1aa45dcd..f3fad310494 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.resolve.checkers import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.Errors @@ -50,7 +51,7 @@ object MissingDependencySupertypeChecker { context.trace, context.missingSupertypesResolver ) - val eagerChecksAllowed = context.languageVersionSettings.supportsFeature(LanguageFeature.ExtendedCompilerChecks) + val eagerChecksAllowed = context.languageVersionSettings.getFlag(AnalysisFlags.extendedCompilerChecks) val unresolvedLazySupertypesByDefault = descriptor is ConstructorDescriptor || descriptor is FakeCallableDescriptorForObject if (eagerChecksAllowed || !unresolvedLazySupertypesByDefault && !errorReported) { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index e7eff53f676..1fd27a05cc3 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -168,8 +168,6 @@ enum class LanguageFeature( // Looks like we can't enable it until KT-26245 is fixed because otherwise some use cases become broken because of overrides ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated(sinceVersion = null, kind = BUG_FIX), - ExtendedCompilerChecks(sinceVersion = null), - // Experimental features Coroutines( From 1664eec7e430ce7829efb0a2c3fb792050e538f2 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Wed, 20 Jan 2021 23:18:36 +0300 Subject: [PATCH 025/153] FIR: report lowering time from JvmIrCodegenFactory --- .../cli/common/CommonCompilerPerformanceManager.kt | 14 ++++++++++++++ .../kotlin/cli/common/performanceMeasurements.kt | 2 +- .../jvm/compiler/KotlinToJVMBytecodeCompiler.kt | 8 ++++++-- .../kotlin/backend/jvm/JvmIrCodegenFactory.kt | 9 +++++++-- .../test/frontend/fir/Fir2IrResultsConverter.kt | 3 ++- .../jetbrains/kotlin/codegen/GenerationUtils.kt | 2 +- 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt index 3085783a6f9..267bb100434 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CommonCompilerPerformanceManager.kt @@ -22,6 +22,7 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str private var startGCData = mutableMapOf() private var irTranslationStart: Long = 0 + private var irLoweringStart: Long = 0 private var irGenerationStart: Long = 0 private var targetDescription: String? = null @@ -88,6 +89,19 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str ) } + open fun notifyIRLoweringStarted() { + irLoweringStart = PerformanceCounter.currentTime() + } + + open fun notifyIRLoweringFinished() { + val time = deltaTime(irLoweringStart) + measurements += IRMeasurement( + lines, + TimeUnit.NANOSECONDS.toMillis(time), + IRMeasurement.Kind.LOWERING + ) + } + open fun notifyIRGenerationStarted() { irGenerationStart = PerformanceCounter.currentTime() } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/performanceMeasurements.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/performanceMeasurements.kt index cc4c492794b..5771c469aa7 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/performanceMeasurements.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/performanceMeasurements.kt @@ -37,7 +37,7 @@ class IRMeasurement(val lines: Int?, val milliseconds: Long, val kind: Kind) : P override fun render(): String = formatMeasurement("IR $kind", milliseconds, lines) enum class Kind { - TRANSLATION, GENERATION + TRANSLATION, LOWERING, GENERATION } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index 867ab0a1bb9..7beaf6b4ffb 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -387,10 +387,14 @@ object KotlinToJVMBytecodeCompiler { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - performanceManager?.notifyIRGenerationStarted() + performanceManager?.notifyIRLoweringStarted() generationState.beforeCompile() codegenFactory.generateModuleInFrontendIRMode( - generationState, moduleFragment, symbolTable, sourceManager, extensions, FirJvmBackendExtension(session, components) + generationState, moduleFragment, symbolTable, sourceManager, extensions, FirJvmBackendExtension(session, components), + { + performanceManager?.notifyIRLoweringFinished() + performanceManager?.notifyIRGenerationStarted() + } ) CodegenFactory.doCheckCancelled(generationState) generationState.factory.done() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index 51a4cb98c19..04e314f7f3b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -49,6 +49,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory val irProviders: List, val extensions: JvmGeneratorExtensions, val backendExtension: JvmBackendExtension, + val notifyCodegenStart: () -> Unit, ) override fun generateModule(state: GenerationState, files: Collection) { @@ -158,6 +159,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory irProviders, extensions, JvmBackendExtension.Default, + {}, ) } @@ -173,7 +175,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory } fun doGenerateFilesInternal(input: JvmIrBackendInput) { - val (state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, backendExtension) = input + val (state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart) = input val context = JvmBackendContext( state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig, extensions, backendExtension @@ -189,6 +191,8 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory JvmLower(context).lower(irModuleFragment) + notifyCodegenStart() + for (generateMultifileFacade in listOf(true, false)) { for (irFile in irModuleFragment.files) { // Generate multifile facades first, to compute and store JVM signatures of const properties which are later used @@ -221,10 +225,11 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory sourceManager: PsiSourceManager, extensions: JvmGeneratorExtensions, backendExtension: JvmBackendExtension, + notifyCodegenStart: () -> Unit ) { val irProviders = configureBuiltInsAndgenerateIrProvidersInFrontendIRMode(irModuleFragment, symbolTable, extensions) doGenerateFilesInternal( - JvmIrBackendInput(state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, backendExtension) + JvmIrBackendInput(state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart) ) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt index 2c82f999c12..d6c5b69a5ae 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt @@ -91,7 +91,8 @@ class Fir2IrResultsConverter( phaseConfig, irProviders, extensions, - FirJvmBackendExtension(inputArtifact.session, components) + FirJvmBackendExtension(inputArtifact.session, components), + {}, ) ) } diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt index 23e10301bca..26c8fc7a309 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt @@ -131,7 +131,7 @@ object GenerationUtils { generationState.beforeCompile() codegenFactory.generateModuleInFrontendIRMode( - generationState, moduleFragment, symbolTable, sourceManager, extensions, FirJvmBackendExtension(session, components), + generationState, moduleFragment, symbolTable, sourceManager, extensions, FirJvmBackendExtension(session, components), {}, ) generationState.factory.done() From 9b6f95faa257cf750726da5eff3e57e6b8ec6f85 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Thu, 4 Feb 2021 17:20:47 +0300 Subject: [PATCH 026/153] FIR: report lowering time in FullPipelineModularizedTest --- .../jetbrains/kotlin/fir/FullPipelineModularizedTest.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FullPipelineModularizedTest.kt b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FullPipelineModularizedTest.kt index b918a6ec6fe..4d2d061d344 100644 --- a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FullPipelineModularizedTest.kt +++ b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FullPipelineModularizedTest.kt @@ -30,11 +30,12 @@ class FullPipelineModularizedTest : AbstractModularizedTest() { val gcInfo: Map, val analysis: Long, val translation: Long, + val lowering: Long, val generation: Long, val files: Int, val lines: Int ) { - constructor() : this(emptyMap(), 0, 0, 0, 0, 0) + constructor() : this(emptyMap(), 0, 0, 0, 0, 0, 0) operator fun plus(other: CumulativeTime): CumulativeTime { return CumulativeTime( @@ -43,13 +44,14 @@ class FullPipelineModularizedTest : AbstractModularizedTest() { }, analysis + other.analysis, translation + other.translation, + lowering + other.lowering, generation + other.generation, files + other.files, lines + other.lines ) } - fun totalTime() = analysis + translation + generation + fun totalTime() = analysis + translation + lowering + generation } private lateinit var totalPassResult: CumulativeTime @@ -126,6 +128,7 @@ class FullPipelineModularizedTest : AbstractModularizedTest() { } phase("Analysis", total.analysis, total.files, total.lines) phase("Translation", total.translation, total.files, total.lines) + phase("Lowering", total.lowering, total.files, total.lines) phase("Generation", total.generation, total.files, total.lines) separator() @@ -264,6 +267,7 @@ class FullPipelineModularizedTest : AbstractModularizedTest() { gcInfo, analysisMeasurement?.milliseconds ?: 0, irMeasurements.firstOrNull { it.kind == IRMeasurement.Kind.TRANSLATION }?.milliseconds ?: 0, + irMeasurements.firstOrNull { it.kind == IRMeasurement.Kind.LOWERING }?.milliseconds ?: 0, irMeasurements.firstOrNull { it.kind == IRMeasurement.Kind.GENERATION }?.milliseconds ?: 0, files ?: 0, lines ?: 0 From 4ed93d3dee25f6f81411980e7ec3984b3955f00a Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Fri, 5 Feb 2021 17:19:55 +0300 Subject: [PATCH 027/153] [IR] Add IrCapturedType into IR type system - support it in TypeSystemContext --- .../kotlin/ir/types/IrTypeSystemContext.kt | 38 ++++++++------ .../kotlin/ir/types/impl/IrSimpleTypeImpl.kt | 1 + .../kotlin/ir/types/impl/IrTypeBase.kt | 52 ++++++++++++++++++- 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index 2b89a9ab30e..a832de72003 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -5,12 +5,11 @@ package org.jetbrains.kotlin.ir.types -import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.DescriptorVisibilities -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns @@ -71,7 +70,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon } } - override fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? = null + override fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? = this as? IrCapturedType override fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker? = null @@ -83,19 +82,24 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon else simpleType.run { IrSimpleTypeImpl(classifier, nullable, arguments, annotations) } } - override fun SimpleTypeMarker.typeConstructor() = (this as IrSimpleType).classifier + override fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker = when (this) { + is IrCapturedType -> constructor + is IrSimpleType -> classifier + else -> error("Unknown type constructor") + } override fun CapturedTypeMarker.typeConstructor(): CapturedTypeConstructorMarker = - error("Captured types should be used for IrTypes") + (this as IrCapturedType).constructor - override fun CapturedTypeMarker.isProjectionNotNull(): Boolean = - error("Captured types should be used for IrTypes") + // Note: `isProjectionNotNull` is used inside inference along with intersection types. + // IrTypes are not used in type inference and do not have intersection type so implemenation is default (false) + override fun CapturedTypeMarker.isProjectionNotNull(): Boolean = false override fun CapturedTypeMarker.captureStatus(): CaptureStatus = - error("Captured types should be used for IrTypes") + (this as IrCapturedType).captureStatus override fun CapturedTypeConstructorMarker.projection(): TypeArgumentMarker = - error("Captured types should be used for IrTypes") + (this as IrCapturedType.Constructor).argument override fun KotlinTypeMarker.argumentsCount(): Int = when (this) { @@ -116,7 +120,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun KotlinTypeMarker.asTypeArgument() = this as IrTypeArgument - override fun CapturedTypeMarker.lowerType(): KotlinTypeMarker? = error("Captured Type is not valid for IrTypes") + override fun CapturedTypeMarker.lowerType(): KotlinTypeMarker? = (this as IrCapturedType).lowerType override fun TypeArgumentMarker.isStarProjection() = this is IrStarProjection @@ -139,6 +143,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun TypeConstructorMarker.supertypes(): Collection { return when (this) { + is IrCapturedType.Constructor -> superTypes is IrClassSymbol -> owner.superTypes is IrTypeParameterSymbol -> owner.superTypes else -> error("unsupported type constructor") @@ -159,11 +164,12 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun TypeParameterMarker.getTypeConstructor() = this as IrTypeParameterSymbol - override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker) = FqNameEqualityChecker.areEqual( - c1 as IrClassifierSymbol, c2 as IrClassifierSymbol - ) + override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean = + if (c1 is IrClassifierSymbol && c2 is IrClassifierSymbol) { + FqNameEqualityChecker.areEqual(c1 , c2) + } else c1 === c2 - override fun TypeConstructorMarker.isDenotable() = true + override fun TypeConstructorMarker.isDenotable() = this !is IrCapturedType.Constructor override fun TypeConstructorMarker.isCommonFinalClassConstructor(): Boolean { val classSymbol = this as? IrClassSymbol ?: return false @@ -185,6 +191,8 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon // TODO: is that correct? require(type is IrSimpleType) + if (type is IrCapturedType) return null + val classifier = type.classifier as? IrClassSymbol ?: return null val typeArguments = type.arguments diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt index daecddcd6fd..dac83e8297e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt @@ -95,6 +95,7 @@ class IrTypeProjectionImpl internal constructor( fun makeTypeProjection(type: IrType, variance: Variance): IrTypeProjection = when { + type is IrCapturedType -> IrTypeProjectionImpl(type, variance) type is IrTypeProjection && type.variance == variance -> type type is IrSimpleType -> type.toBuilder().apply { this.variance = variance }.buildTypeProjection() type is IrDynamicType -> IrDynamicTypeImpl(null, type.annotations, variance) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeBase.kt index 7bbc6f0859d..edc84085d34 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeBase.kt @@ -6,11 +6,15 @@ package org.jetbrains.kotlin.ir.types.impl import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.model.CaptureStatus +import org.jetbrains.kotlin.types.model.CapturedTypeConstructorMarker +import org.jetbrains.kotlin.types.model.CapturedTypeMarker import org.jetbrains.kotlin.utils.addToStdlib.safeAs abstract class IrTypeBase(val kotlinType: KotlinType?) : IrType, IrTypeProjection { @@ -69,3 +73,49 @@ object IrUninitializedType : IrType { class ReturnTypeIsNotInitializedException(function: IrFunction) : IllegalStateException( "Return type is not initialized for function '${function.name}'" ) + + +// Please note this type is not denotable which means it could only exist inside type system +class IrCapturedType( + val captureStatus: CaptureStatus, + val lowerType: IrType?, + projection: IrTypeArgument, + typeParameter: IrTypeParameter +) : IrSimpleType, CapturedTypeMarker { + + class Constructor(val argument: IrTypeArgument, val typeParameter: IrTypeParameter) : + CapturedTypeConstructorMarker { + + private var _superTypes: List = emptyList() + + val superTypes: List get() = _superTypes + + fun initSuperTypes(superTypes: List) { + _superTypes = superTypes + } + } + + val constructor: Constructor = Constructor(projection, typeParameter) + + override val classifier: IrClassifierSymbol get() = error("Captured Type does not have a classifier") + override val arguments: List get() = emptyList() + override val abbreviation: IrTypeAbbreviation? get () = null + override val hasQuestionMark: Boolean get() = false + override val annotations: List get() = emptyList() + + override fun equals(other: Any?): Boolean { + return other is IrCapturedType + && captureStatus == other.captureStatus + && lowerType == other.lowerType + && constructor.argument == other.constructor.argument + && constructor.typeParameter == other.constructor.typeParameter + && constructor.superTypes == other.constructor.superTypes + } + + override fun hashCode(): Int { + return (((captureStatus.hashCode() * 31 + + (lowerType?.hashCode() ?: 0)) * 31 + + constructor.argument.hashCode()) * 31 + + constructor.typeParameter.hashCode()) + constructor.superTypes.hashCode() + } +} \ No newline at end of file From 79f986bb75ff5180a90a71e375b0ee8acb74ed93 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Fri, 5 Feb 2021 17:21:56 +0300 Subject: [PATCH 028/153] [IR] Fix IrType equality in case of complex variance - reimplement type capturing on top of pure IrCaptureType - add captured type substitutor - fix #KT-43831 --- .../kotlin/ir/types/IrTypeSubstitutor.kt | 76 ++++++++++++++----- .../kotlin/ir/types/IrTypeSystemContext.kt | 48 +++++++++--- 2 files changed, 94 insertions(+), 30 deletions(-) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt index 795946150b4..29d5c1ad670 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt @@ -7,41 +7,29 @@ package org.jetbrains.kotlin.ir.types import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.impl.IrCapturedType import org.jetbrains.kotlin.ir.types.impl.buildSimpleType import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.toBuilder import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker -class IrTypeSubstitutor( - typeParameters: List, - typeArguments: List, - private val irBuiltIns: IrBuiltIns -): TypeSubstitutorMarker { - init { - assert(typeParameters.size == typeArguments.size) { - "Unexpected number of type arguments: ${typeArguments.size}\n" + - "Type parameters are:\n" + - typeParameters.joinToString(separator = "\n") { it.owner.render() } + - "Type arguments are:\n" + - typeArguments.joinToString(separator = "\n") { it.render() } - } - } +abstract class AbstractIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : TypeSubstitutorMarker { - private val substitution = typeParameters.zip(typeArguments).toMap() private fun IrType.typeParameterConstructor(): IrTypeParameterSymbol? { return if (this is IrSimpleType) classifier as? IrTypeParameterSymbol else null } - private fun getSubstitutionArgument(typeParameter: IrTypeParameterSymbol): IrTypeArgument = - substitution[typeParameter] - ?: throw AssertionError("Unsubstituted type parameter: ${typeParameter.owner.render()}") + abstract fun getSubstitutionArgument(typeParameter: IrTypeParameterSymbol): IrTypeArgument + + abstract fun isEmptySubstitution(): Boolean fun substitute(type: IrType): IrType { - if (substitution.isEmpty()) return type + if (isEmptySubstitution()) return type return type.typeParameterConstructor()?.let { when (val typeArgument = getSubstitutionArgument(it)) { @@ -84,3 +72,53 @@ class IrTypeSubstitutor( return makeTypeProjection(substituteType(typeArgument.type), typeArgument.variance) } } + + +class IrTypeSubstitutor( + typeParameters: List, + typeArguments: List, + irBuiltIns: IrBuiltIns +) : AbstractIrTypeSubstitutor(irBuiltIns) { + + init { + assert(typeParameters.size == typeArguments.size) { + "Unexpected number of type arguments: ${typeArguments.size}\n" + + "Type parameters are:\n" + + typeParameters.joinToString(separator = "\n") { it.owner.render() } + + "Type arguments are:\n" + + typeArguments.joinToString(separator = "\n") { it.render() } + } + } + + private val substitution = typeParameters.zip(typeArguments).toMap() + + override fun getSubstitutionArgument(typeParameter: IrTypeParameterSymbol): IrTypeArgument = + substitution[typeParameter] + ?: throw AssertionError("Unsubstituted type parameter: ${typeParameter.owner.render()}") + + override fun isEmptySubstitution(): Boolean = substitution.isEmpty() +} + +class IrCapturedTypeSubstitutor( + typeParameters: List, + typeArguments: List, + capturedTypes: List, + irBuiltIns: IrBuiltIns +) : AbstractIrTypeSubstitutor(irBuiltIns) { + + init { + assert(typeArguments.size == typeParameters.size) + assert(capturedTypes.size == typeParameters.size) + } + + private val oldSubstitution = typeParameters.zip(typeArguments).toMap() + private val capturedSubstitution = typeParameters.zip(capturedTypes).toMap() + + override fun getSubstitutionArgument(typeParameter: IrTypeParameterSymbol): IrTypeArgument { + return capturedSubstitution[typeParameter]?.let { makeTypeProjection(it, Variance.INVARIANT) } + ?: oldSubstitution[typeParameter] + ?: throw AssertionError("Unsubstituted type parameter: ${typeParameter.owner.render()}") + } + + override fun isEmptySubstitution(): Boolean = oldSubstitution.isEmpty() +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index a832de72003..7eca8a677a8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -184,7 +184,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon * * In this case Captured Type of `y` would be `Array` * - * See https://jetbrains.github.io/kotlin-spec/#type-capturing + * See https://kotlinlang.org/spec/type-system.html#type-capturing */ override fun captureFromArguments(type: SimpleTypeMarker, status: CaptureStatus): SimpleTypeMarker? { @@ -204,23 +204,49 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon if (typeArguments.all { it is IrTypeProjection && it.variance == Variance.INVARIANT }) return type - val newArguments = mutableListOf() + val capturedTypes = ArrayList(typeArguments.size) + for (index in typeArguments.indices) { - val argument = typeArguments[index] val parameter = typeParameters[index] + val argument = typeArguments[index] if (argument is IrTypeProjection && argument.variance == Variance.INVARIANT) { - newArguments += argument - continue + capturedTypes.add(null) + } else { + val lowerType = if (argument is IrTypeProjection && argument.variance == Variance.IN_VARIANCE) { + argument.type + } else null + + capturedTypes.add(IrCapturedType(status, lowerType, argument, parameter)) } + } - val additionalBounds = - if (argument is IrTypeProjection && argument.variance == Variance.OUT_VARIANCE) listOf(argument.type) else emptyList() + val newArguments = ArrayList(typeArguments.size) - newArguments += makeTypeProjection( - makeTypeIntersection(parameter.superTypes + additionalBounds), - Variance.INVARIANT - ) + val typeSubstitutor = IrCapturedTypeSubstitutor(typeParameters.map { it.symbol }, typeArguments, capturedTypes, irBuiltIns) + + for (index in typeArguments.indices) { + val oldArgument = typeArguments[index] + val parameter = typeParameters[index] + val capturedType = capturedTypes[index] + + if (capturedType == null) { + assert(oldArgument is IrTypeProjection && oldArgument.variance == Variance.INVARIANT) + newArguments.add(oldArgument) + } else { + val capturedSuperTypes = mutableListOf() + parameter.superTypes.mapTo(capturedSuperTypes) { + typeSubstitutor.substitute(it) + } + + if (oldArgument is IrTypeProjection && oldArgument.variance == Variance.OUT_VARIANCE) { + capturedSuperTypes += oldArgument.type + } + + capturedType.constructor.initSuperTypes(capturedSuperTypes) + + newArguments.add(makeTypeProjection(capturedType, Variance.INVARIANT)) + } } return IrSimpleTypeImpl(type.classifier, type.hasQuestionMark, newArguments, type.annotations) From ca6e1b8f1b58daa8e63ced7c3655145d7939e613 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Fri, 5 Feb 2021 17:22:22 +0300 Subject: [PATCH 029/153] Add box test for #KT-43831 --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++ .../box/fakeOverride/varianceOverload.kt | 63 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++ .../LightAnalysisModeTestGenerated.java | 5 ++ .../IrJsCodegenBoxES6TestGenerated.java | 5 ++ .../IrJsCodegenBoxTestGenerated.java | 5 ++ .../semantics/JsCodegenBoxTestGenerated.java | 5 ++ .../IrCodegenBoxWasmTestGenerated.java | 5 ++ 9 files changed, 106 insertions(+) create mode 100644 compiler/testData/codegen/box/fakeOverride/varianceOverload.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 7f21b3dbeda..e7801da77da 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -14629,6 +14629,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testPropertySetter() throws Exception { runTest("compiler/testData/codegen/box/fakeOverride/propertySetter.kt"); } + + @Test + @TestMetadata("varianceOverload.kt") + public void testVarianceOverload() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/varianceOverload.kt"); + } } @Nested diff --git a/compiler/testData/codegen/box/fakeOverride/varianceOverload.kt b/compiler/testData/codegen/box/fakeOverride/varianceOverload.kt new file mode 100644 index 00000000000..fa9a4698c7c --- /dev/null +++ b/compiler/testData/codegen/box/fakeOverride/varianceOverload.kt @@ -0,0 +1,63 @@ + +// MODULE: lib +// FILE: lib.kt +// KT-43831 + + +var result = "FAIL" + +class Change : IsChange { + + override fun qux(select: RPPG1): IsChange? { + result = "" + return null + } + + override fun foo(select: RPPG1, sss: RPPG1): Change? { + result += "O" + return null + } + + override fun bar(a: RPPG2>, b: RPPG3, out AC3>): Change? { + result += "K" + return null + } + +} + +interface IsChange { + fun qux(select: RPPG1): IsChange? + + fun foo(select: RPPG1, sss: RPPG1): IsChange? + + + fun bar(a: RPPG2>, b: RPPG3, out AC3>): IsChange? +} + +abstract class AC1 : BAC1() +abstract class AC2 : BAC2() +abstract class AC3 : BAC3() + +interface I1 +interface I2 +interface I3 + +abstract class BAC1 : I1 +abstract class BAC2 : I2 +abstract class BAC3 : I3 + +class RPPG1 +class RPPG2 +class RPPG3 + +// MODULE: main(lib) +// FILE: main.kt + +fun box(): String { + val c = Change() + c.qux(RPPG1()) + c.foo(RPPG1(), RPPG1()) + c.bar(RPPG2(), RPPG3()) + return result + +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 4fabe55fdda..e9208134610 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -14629,6 +14629,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testPropertySetter() throws Exception { runTest("compiler/testData/codegen/box/fakeOverride/propertySetter.kt"); } + + @Test + @TestMetadata("varianceOverload.kt") + public void testVarianceOverload() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/varianceOverload.kt"); + } } @Nested diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 32b9bcdcee2..d0cbbdb125c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -14629,6 +14629,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testPropertySetter() throws Exception { runTest("compiler/testData/codegen/box/fakeOverride/propertySetter.kt"); } + + @Test + @TestMetadata("varianceOverload.kt") + public void testVarianceOverload() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/varianceOverload.kt"); + } } @Nested diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index f89ad546ddd..acb06b859ba 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -12078,6 +12078,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testPropertySetter() throws Exception { runTest("compiler/testData/codegen/box/fakeOverride/propertySetter.kt"); } + + @TestMetadata("varianceOverload.kt") + public void testVarianceOverload() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/varianceOverload.kt"); + } } @TestMetadata("compiler/testData/codegen/box/fieldRename") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 791de4bd8af..36e343d0123 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -10713,6 +10713,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes public void testPropertySetter() throws Exception { runTest("compiler/testData/codegen/box/fakeOverride/propertySetter.kt"); } + + @TestMetadata("varianceOverload.kt") + public void testVarianceOverload() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/varianceOverload.kt"); + } } @TestMetadata("compiler/testData/codegen/box/fieldRename") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 9a1556f7db5..a90c4995b66 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -10198,6 +10198,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testPropertySetter() throws Exception { runTest("compiler/testData/codegen/box/fakeOverride/propertySetter.kt"); } + + @TestMetadata("varianceOverload.kt") + public void testVarianceOverload() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/varianceOverload.kt"); + } } @TestMetadata("compiler/testData/codegen/box/fieldRename") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 44ef736c75e..1c1d05da831 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -10198,6 +10198,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testPropertySetter() throws Exception { runTest("compiler/testData/codegen/box/fakeOverride/propertySetter.kt"); } + + @TestMetadata("varianceOverload.kt") + public void testVarianceOverload() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/varianceOverload.kt"); + } } @TestMetadata("compiler/testData/codegen/box/fieldRename") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 77f4dddc959..f1673cf96e0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -5172,6 +5172,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest public void testPropertySetter() throws Exception { runTest("compiler/testData/codegen/box/fakeOverride/propertySetter.kt"); } + + @TestMetadata("varianceOverload.kt") + public void testVarianceOverload() throws Exception { + runTest("compiler/testData/codegen/box/fakeOverride/varianceOverload.kt"); + } } @TestMetadata("compiler/testData/codegen/box/fieldRename") From d97a2b13c0623595cd07b6b6b948b8b4a572364b Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Mon, 8 Feb 2021 14:43:33 +0300 Subject: [PATCH 030/153] [Plugin API] Add API to load top level declaration by its signature - request from JP Compose, #KT-44100 --- .../common/extensions/IrPluginContext.kt | 5 +++++ .../common/extensions/IrPluginContextImpl.kt | 11 +++++++++++ .../kotlin/ir/linkage/IrDeserializer.kt | 10 ++++++++++ .../common/serialization/KotlinIrLinker.kt | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContext.kt index 858c8b57d38..633580fe3f6 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContext.kt @@ -10,7 +10,9 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.builders.IrGeneratorContext +import org.jetbrains.kotlin.ir.linkage.IrDeserializer import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable import org.jetbrains.kotlin.ir.util.TypeTranslator @@ -51,4 +53,7 @@ interface IrPluginContext : IrGeneratorContext { fun referenceConstructors(classFqn: FqName): Collection fun referenceFunctions(fqName: FqName): Collection fun referenceProperties(fqName: FqName): Collection + + // temporary solution to load synthetic top-level declaration + fun referenceTopLevel(signature: IdSignature, kind: IrDeserializer.TopLevelSymbolKind, moduleDescriptor: ModuleDescriptor): IrSymbol? } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContextImpl.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContextImpl.kt index bf8da2ef0ba..7de0210fbff 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContextImpl.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContextImpl.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.linkage.IrDeserializer import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable import org.jetbrains.kotlin.ir.util.TypeTranslator @@ -134,4 +135,14 @@ open class IrPluginContextImpl constructor( descriptors.map { st.referenceProperty(it) } } } + + override fun referenceTopLevel( + signature: IdSignature, + kind: IrDeserializer.TopLevelSymbolKind, + moduleDescriptor: ModuleDescriptor + ): IrSymbol? { + val symbol = linker.resolveBySignatureInModule(signature, kind, moduleDescriptor.name) + linker.postProcess() + return symbol + } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/IrDeserializer.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/IrDeserializer.kt index c6a4407ef6b..015911d9dc8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/IrDeserializer.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/IrDeserializer.kt @@ -9,6 +9,8 @@ import org.jetbrains.kotlin.ir.builders.TranslationPluginContext import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.name.Name interface IrDeserializer : IrProvider { @@ -16,6 +18,14 @@ interface IrDeserializer : IrProvider { fun resolveSymbol(symbol: IrSymbol, context: TranslationPluginContext): IrDeclaration? = null } + enum class TopLevelSymbolKind { + FUNCTION_SYMBOL, + CLASS_SYMBOL, + PROPERTY_SYMBOL, + TYPEALIAS_SYMBOL; + } + fun init(moduleFragment: IrModuleFragment?, extensions: Collection) {} + fun resolveBySignatureInModule(signature: IdSignature, kind: TopLevelSymbolKind, moduleName: Name): IrSymbol fun postProcess() {} } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt index 432fd54ea8c..177775d8b70 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance import org.jetbrains.kotlin.resolve.descriptorUtil.module @@ -64,6 +65,7 @@ abstract class KotlinIrLinker( private val modulesWithReachableTopLevels = mutableSetOf() + // TODO: replace with Map protected val deserializersForModules = mutableMapOf() abstract val fakeOverrideBuilder: FakeOverrideBuilder @@ -665,6 +667,23 @@ abstract class KotlinIrLinker( // symbolTable.noUnboundLeft("unbound after fake overrides:") } + private fun topLevelKindToSymbolKind(kind: IrDeserializer.TopLevelSymbolKind): BinarySymbolData.SymbolKind { + return when (kind) { + IrDeserializer.TopLevelSymbolKind.CLASS_SYMBOL -> BinarySymbolData.SymbolKind.CLASS_SYMBOL + IrDeserializer.TopLevelSymbolKind.PROPERTY_SYMBOL -> BinarySymbolData.SymbolKind.PROPERTY_SYMBOL + IrDeserializer.TopLevelSymbolKind.FUNCTION_SYMBOL -> BinarySymbolData.SymbolKind.FUNCTION_SYMBOL + IrDeserializer.TopLevelSymbolKind.TYPEALIAS_SYMBOL -> BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL + } + } + + override fun resolveBySignatureInModule(signature: IdSignature, kind: IrDeserializer.TopLevelSymbolKind, moduleName: Name): IrSymbol { + val moduleDeserializer = + deserializersForModules.entries.find { it.key.name == moduleName }?.value ?: error("No module for name '$moduleName' found") + assert(signature == signature.topLevelSignature()) { "Signature '$signature' has to be top level" } + if (signature !in moduleDeserializer) error("No signature $signature in module $moduleName") + return moduleDeserializer.deserializeIrSymbol(signature, topLevelKindToSymbolKind(kind)) + } + // The issue here is that an expect can not trigger its actual deserialization by reachability // because the expect can not see the actual higher in the module dependency dag. // So we force deserialization of actuals for all deserialized expect symbols here. From 58d903c63869029a4181cbad922a2a2fbb4c0072 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Thu, 4 Feb 2021 11:59:23 -0800 Subject: [PATCH 031/153] [FIR IDE] Make KtSmartcastProvider report resolved smartcast type --- ...ExpressionsSmartcastHighlightingVisitor.kt | 28 ++++++++----------- .../frontend/api/ImplicitReceiverSmartCast.kt | 2 +- .../idea/frontend/api/KtAnalysisSession.kt | 6 ++-- .../api/components/KtSmartCastProvider.kt | 4 +-- .../fir/components/KtFirSmartcastProvider.kt | 20 ++++++------- 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/ExpressionsSmartcastHighlightingVisitor.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/ExpressionsSmartcastHighlightingVisitor.kt index eb8c0166d41..26b8020cd11 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/ExpressionsSmartcastHighlightingVisitor.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/ExpressionsSmartcastHighlightingVisitor.kt @@ -8,8 +8,8 @@ package org.jetbrains.kotlin.idea.fir.highlighter.visitors import com.intellij.lang.annotation.AnnotationHolder import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle -import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors import org.jetbrains.kotlin.psi.* @@ -18,25 +18,23 @@ internal class ExpressionsSmartcastHighlightingVisitor( holder: AnnotationHolder ) : FirAfterResolveHighlightingVisitor(analysisSession, holder) { override fun visitExpression(expression: KtExpression) = with(analysisSession) { - expression.getImplicitReceiverSmartCasts().forEach { (types, kind) -> + expression.getImplicitReceiverSmartCast().forEach { (type, kind) -> val receiverName = when (kind) { ImplicitReceiverSmartcastKind.EXTENSION -> KotlinIdeaAnalysisBundle.message("extension.implicit.receiver") ImplicitReceiverSmartcastKind.DISPATCH -> KotlinIdeaAnalysisBundle.message("implicit.receiver") } - types.forEach { type -> - createInfoAnnotation( - expression, - KotlinIdeaAnalysisBundle.message( - "0.smart.cast.to.1", - receiverName, - type.asStringForDebugging() - ), - KotlinHighlightingColors.SMART_CAST_RECEIVER - ) - } + createInfoAnnotation( + expression, + KotlinIdeaAnalysisBundle.message( + "0.smart.cast.to.1", + receiverName, + type.asStringForDebugging() + ), + KotlinHighlightingColors.SMART_CAST_RECEIVER + ) } - expression.getSmartCasts()?.forEach { type -> + expression.getSmartCast()?.let { type -> createInfoAnnotation( getSmartCastTarget(expression), KotlinIdeaAnalysisBundle.message( @@ -47,8 +45,6 @@ internal class ExpressionsSmartcastHighlightingVisitor( ) } - //todo smartcast to null - super.visitExpression(expression) } } diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/ImplicitReceiverSmartCast.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/ImplicitReceiverSmartCast.kt index 5e63a8a034b..09de7bbdb92 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/ImplicitReceiverSmartCast.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/ImplicitReceiverSmartCast.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.frontend.api import org.jetbrains.kotlin.idea.frontend.api.types.KtType -data class ImplicitReceiverSmartCast(val types: Collection, val kind: ImplicitReceiverSmartcastKind) +data class ImplicitReceiverSmartCast(val type: KtType, val kind: ImplicitReceiverSmartcastKind) enum class ImplicitReceiverSmartcastKind { DISPATCH, EXTENSION diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index a768ed8d6d5..f06355cd03a 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt @@ -61,10 +61,10 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali fun KtCallableSymbol.getIntersectionOverriddenSymbols(): Collection = symbolDeclarationOverridesProvider.getIntersectionOverriddenSymbols(this) - fun KtExpression.getSmartCasts(): Collection = smartCastProvider.getSmartCastedToTypes(this) + fun KtExpression.getSmartCast(): KtType? = smartCastProvider.getSmartCastedToType(this) - fun KtExpression.getImplicitReceiverSmartCasts(): Collection = - smartCastProvider.getImplicitReceiverSmartCasts(this) + fun KtExpression.getImplicitReceiverSmartCast(): Collection = + smartCastProvider.getImplicitReceiverSmartCast(this) fun KtExpression.getKtType(): KtType = expressionTypeProvider.getKtExpressionType(this) diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtSmartCastProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtSmartCastProvider.kt index 1c80a97dcb8..415804c1af2 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtSmartCastProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtSmartCastProvider.kt @@ -10,6 +10,6 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.psi.KtExpression abstract class KtSmartCastProvider : KtAnalysisSessionComponent() { - abstract fun getSmartCastedToTypes(expression: KtExpression): Collection - abstract fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection + abstract fun getSmartCastedToType(expression: KtExpression): KtType? + abstract fun getImplicitReceiverSmartCast(expression: KtExpression): Collection } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirSmartcastProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirSmartcastProvider.kt index 7e6bb935144..25dc4adc57f 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirSmartcastProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirSmartcastProvider.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartCast import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind @@ -20,18 +22,16 @@ import org.jetbrains.kotlin.psi.KtExpression internal class KtFirSmartcastProvider( override val analysisSession: KtFirAnalysisSession, override val token: ValidityToken, - ) : KtSmartCastProvider(), KtFirAnalysisSessionComponent { - override fun getSmartCastedToTypes(expression: KtExpression): Collection = withValidityAssertion { - // TODO filter out not used smartcasts +) : KtSmartCastProvider(), KtFirAnalysisSessionComponent { + override fun getSmartCastedToType(expression: KtExpression): KtType? = withValidityAssertion { expression.getOrBuildFirSafe(analysisSession.firResolveState) - ?.typesFromSmartCast - ?.map { it.asKtType() } - ?: emptyList() + ?.typeRef + ?.coneTypeSafe() + ?.asKtType() } @OptIn(ExperimentalStdlibApi::class) - override fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection = withValidityAssertion { - // TODO filter out not used smartcasts + override fun getImplicitReceiverSmartCast(expression: KtExpression): Collection = withValidityAssertion { val qualifiedExpression = expression.getOrBuildFirSafe(analysisSession.firResolveState) ?: return emptyList() if (qualifiedExpression.dispatchReceiver !is FirExpressionWithSmartcast @@ -40,13 +40,13 @@ internal class KtFirSmartcastProvider( buildList { (qualifiedExpression.dispatchReceiver as? FirExpressionWithSmartcast)?.let { smartCasted -> ImplicitReceiverSmartCast( - smartCasted.typesFromSmartCast.map { it.asKtType() }, + smartCasted.typeRef.coneTypeSafe()?.asKtType() ?: return@let null, ImplicitReceiverSmartcastKind.DISPATCH ) }?.let(::add) (qualifiedExpression.extensionReceiver as? FirExpressionWithSmartcast)?.let { smartCasted -> ImplicitReceiverSmartCast( - smartCasted.typesFromSmartCast.map { it.asKtType() }, + smartCasted.typeRef.coneTypeSafe()?.asKtType() ?: return@let null, ImplicitReceiverSmartcastKind.EXTENSION ) }?.let(::add) From 10cc86c975612284a3f656b86fbad16254fab6a9 Mon Sep 17 00:00:00 2001 From: Andrey Zinovyev Date: Tue, 9 Feb 2021 13:32:27 +0300 Subject: [PATCH 032/153] [KAPT] Warn about usage of types from default package Java doesn't support import from default package. We can't fix it, so we warn about it. #KT-36743 --- .../KaptToolIntegrationTestGenerated.java | 4 +- .../integration/defaultPackage/RootClass.kt | 1 + .../integration/defaultPackage/Usage.kt | 7 ++ .../integration/defaultPackage/build.txt | 36 ++++++ .../stubs/ClassFileToSourceStubConverter.kt | 116 +++++++++++++----- ...ileToSourceStubConverterTestGenerated.java | 10 ++ ...ileToSourceStubConverterTestGenerated.java | 10 ++ .../testData/converter/defaultPackage.kt | 45 +++++++ .../testData/converter/defaultPackage.txt | 72 +++++++++++ .../defaultPackageCorrectErrorTypes.kt | 46 +++++++ .../defaultPackageCorrectErrorTypes.txt | 72 +++++++++++ 11 files changed, 386 insertions(+), 33 deletions(-) create mode 100644 plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/RootClass.kt create mode 100644 plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/Usage.kt create mode 100644 plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/build.txt create mode 100644 plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.kt create mode 100644 plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.txt create mode 100644 plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.kt create mode 100644 plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.txt diff --git a/plugins/kapt3/kapt3-cli/test/org/jetbrains/kotlin/kapt/cli/test/KaptToolIntegrationTestGenerated.java b/plugins/kapt3/kapt3-cli/test/org/jetbrains/kotlin/kapt/cli/test/KaptToolIntegrationTestGenerated.java index 9c880effdfb..44c26562292 100644 --- a/plugins/kapt3/kapt3-cli/test/org/jetbrains/kotlin/kapt/cli/test/KaptToolIntegrationTestGenerated.java +++ b/plugins/kapt3/kapt3-cli/test/org/jetbrains/kotlin/kapt/cli/test/KaptToolIntegrationTestGenerated.java @@ -29,9 +29,9 @@ public class KaptToolIntegrationTestGenerated extends AbstractKaptToolIntegratio KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kapt3/kapt3-cli/testData/integration"), Pattern.compile("^([^\\.]+)$"), null, false); } - @TestMetadata("argfile") + @TestMetadata("defaultPackage") public void testArgfile() throws Exception { - runTest("plugins/kapt3/kapt3-cli/testData/integration/argfile/"); + runTest("plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/"); } @TestMetadata("correctErrorTypesOff") diff --git a/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/RootClass.kt b/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/RootClass.kt new file mode 100644 index 00000000000..568ed8a64f4 --- /dev/null +++ b/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/RootClass.kt @@ -0,0 +1 @@ +class RootClass diff --git a/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/Usage.kt b/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/Usage.kt new file mode 100644 index 00000000000..d6e1e0c3cec --- /dev/null +++ b/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/Usage.kt @@ -0,0 +1,7 @@ +package test + +import RootClass + +interface Usage { + fun test(): RootClass +} diff --git a/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/build.txt b/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/build.txt new file mode 100644 index 00000000000..08ef3b796e3 --- /dev/null +++ b/plugins/kapt3/kapt3-cli/testData/integration/defaultPackage/build.txt @@ -0,0 +1,36 @@ +# copy +../simple/ap +ap + +# mkdir +output/ap +output/stubs +output/classes +output/javaClasses +output/sources + +# kotlinc +-cp %KOTLIN_STDLIB% +-d output/ap +ap/Processor.kt + +# kapt +-Kapt-stubs=output/stubs +-Kapt-classes=output/classes +-Kapt-sources=output/sources +-Kapt-classpath=output/ap +-Kapt-processors=apt.SampleApt +-d output/classes +-cp output/ap:%KOTLIN_STDLIB% +RootClass.kt +Usage.kt + +# after +Return code: 1 + +warning: [kapt] test.Usage: Can't reference type 'RootClass' from default package in Java stub. +error: output/stubs/test/Usage.java:9: error: cannot find symbol + public abstract RootClass test(); + ^ + symbol: class RootClass + location: interface Usage diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index b4d341740d8..28d4c3a64c6 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -51,6 +51,7 @@ import org.jetbrains.kotlin.kapt3.util.* import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.load.kotlin.TypeMappingMode import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.isOneSegmentFQN import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DelegatingBindingTrace @@ -130,6 +131,8 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati private val kdocCommentKeeper = KDocCommentKeeper(kaptContext) + private val importsFromRoot by lazy(::collectImportsFromRootPackage) + private var done = false fun convert(): List { @@ -249,7 +252,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati } private fun convertImports(file: KtFile, classDeclaration: JCClassDecl): JavacList { - val imports = mutableListOf() + val imports = mutableListOf() val importedShortNames = mutableSetOf() // We prefer ordinary imports over aliased ones. @@ -321,6 +324,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati val isAnnotation = clazz.isAnnotation() val modifiers = convertModifiers( + clazz, flags, if (isEnum) ElementKind.ENUM else ElementKind.CLASS, packageFqName, clazz.visibleAnnotations, clazz.invisibleAnnotations, descriptor.annotations @@ -375,7 +379,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati it.name == "" && Type.getArgumentsAndReturnSizes(it.desc).shr(2) >= 2 }?.desc ?: "()Z") - val args = mapJList(constructorArguments.drop(2)) { convertLiteralExpression(getDefaultValue(it)) } + val args = mapJList(constructorArguments.drop(2)) { convertLiteralExpression(clazz, getDefaultValue(it)) } val def = data.correspondingClass?.let { convertClass(it, lineMappings, packageFqName, false) } @@ -624,6 +628,8 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati return false } + reportIfIllegalTypeUsage(containingClass, type) + return true } @@ -684,6 +690,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati } ?: Annotations.EMPTY val modifiers = convertModifiers( + containingClass, field.access, ElementKind.FIELD, packageFqName, field.visibleAnnotations, field.invisibleAnnotations, fieldAnnotations ) @@ -714,7 +721,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati lineMappings.registerField(containingClass, field) - val initializer = explicitInitializer ?: convertPropertyInitializer(field) + val initializer = explicitInitializer ?: convertPropertyInitializer(containingClass, field) return treeMaker.VarDef(modifiers, treeMaker.name(name), typeExpression, initializer).also { if (keepKdocComments) { it.keepKdocComments(field) @@ -722,7 +729,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati } } - private fun convertPropertyInitializer(field: FieldNode): JCExpression? { + private fun convertPropertyInitializer(containingClass: ClassNode, field: FieldNode): JCExpression? { val value = field.value val origin = kaptContext.origins[field] @@ -735,7 +742,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati if (value != null) { if (propertyInitializer != null) { - return convertConstantValueArguments(value, listOf(propertyInitializer)) + return convertConstantValueArguments(containingClass, value, listOf(propertyInitializer)) } return convertValueOfPrimitiveTypeOrString(value) @@ -759,14 +766,14 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati if (constValue != null) { val asmValue = mapConstantValueToAsmRepresentation(constValue) if (asmValue !== UnknownConstantValue) { - return convertConstantValueArguments(asmValue, listOf(propertyInitializer)) + return convertConstantValueArguments(containingClass, asmValue, listOf(propertyInitializer)) } } } if (isFinal(field.access)) { val type = Type.getType(field.desc) - return convertLiteralExpression(getDefaultValue(type)) + return convertLiteralExpression(containingClass, getDefaultValue(type)) } return null @@ -879,6 +886,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati if (!isValidIdentifier(name, canBeConstructor = isConstructor)) return null val modifiers = convertModifiers( + containingClass, if (containingClass.isEnum() && isConstructor) (method.access.toLong() and VISIBILITY_MODIFIERS.inv()) else @@ -908,6 +916,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati val varargs = if (lastParameter && isArrayType && method.isVarargs()) Flags.VARARGS else 0L val modifiers = convertModifiers( + containingClass, info.flags or varargs or Flags.PARAMETER, ElementKind.PARAMETER, packageFqName, @@ -925,9 +934,9 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati val valueParametersFromDescriptor = descriptor.valueParameters val (genericSignature, returnType) = - extractMethodSignatureTypes(descriptor, exceptionTypes, jcReturnType, method, parameters, valueParametersFromDescriptor) + extractMethodSignatureTypes(descriptor, exceptionTypes, jcReturnType, method, parameters, valueParametersFromDescriptor) - val defaultValue = method.annotationDefault?.let { convertLiteralExpression(it) } + val defaultValue = method.annotationDefault?.let { convertLiteralExpression(containingClass, it) } val body = if (defaultValue != null) { null @@ -943,7 +952,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati val superClassConstructorCall = if (superClassConstructor != null) { val args = mapJList(superClassConstructor.valueParameters) { param -> - convertLiteralExpression(getDefaultValue(typeMapper.mapType(param.type))) + convertLiteralExpression(containingClass, getDefaultValue(typeMapper.mapType(param.type))) } val call = treeMaker.Apply(JavacList.nil(), treeMaker.SimpleName("super"), args) JavacList.of(treeMaker.Exec(call)) @@ -955,7 +964,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati } else if (asmReturnType == Type.VOID_TYPE) { treeMaker.Block(0, JavacList.nil()) } else { - val returnStatement = treeMaker.Return(convertLiteralExpression(getDefaultValue(asmReturnType))) + val returnStatement = treeMaker.Return(convertLiteralExpression(containingClass, getDefaultValue(asmReturnType))) treeMaker.Block(0, JavacList.of(returnStatement)) } @@ -1112,15 +1121,25 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati @Suppress("NOTHING_TO_INLINE") private inline fun convertModifiers( + containingClass: ClassNode, access: Int, kind: ElementKind, packageFqName: String, visibleAnnotations: List?, invisibleAnnotations: List?, descriptorAnnotations: Annotations - ): JCModifiers = convertModifiers(access.toLong(), kind, packageFqName, visibleAnnotations, invisibleAnnotations, descriptorAnnotations) + ): JCModifiers = convertModifiers( + containingClass, + access.toLong(), + kind, + packageFqName, + visibleAnnotations, + invisibleAnnotations, + descriptorAnnotations + ) private fun convertModifiers( + containingClass: ClassNode, access: Long, kind: ElementKind, packageFqName: String, @@ -1135,7 +1154,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati seenOverride = true } val annotationDescriptor = descriptorAnnotations.singleOrNull { checkIfAnnotationValueMatches(annotation, AnnotationValue(it)) } - val annotationTree = convertAnnotation(annotation, packageFqName, annotationDescriptor) ?: return list + val annotationTree = convertAnnotation(containingClass, annotation, packageFqName, annotationDescriptor) ?: return list return list.prepend(annotationTree) } @@ -1159,6 +1178,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati } private fun convertAnnotation( + containingClass: ClassNode, annotation: AnnotationNode, packageFqName: String? = "", annotationDescriptor: AnnotationDescriptor? = null, @@ -1190,25 +1210,30 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati val values = if (argMapping.isNotEmpty()) { argMapping.mapNotNull { (parameterName, arg) -> if (arg is DefaultValueArgument) return@mapNotNull null - convertAnnotationArgumentWithName(constantValues[parameterName], arg, parameterName) + convertAnnotationArgumentWithName(containingClass, constantValues[parameterName], arg, parameterName) } } else { constantValues.mapNotNull { (parameterName, arg) -> - convertAnnotationArgumentWithName(arg, null, parameterName) + convertAnnotationArgumentWithName(containingClass, arg, null, parameterName) } } return treeMaker.Annotation(annotationFqName, JavacList.from(values)) } - private fun convertAnnotationArgumentWithName(constantValue: Any?, value: ResolvedValueArgument?, name: String): JCExpression? { + private fun convertAnnotationArgumentWithName( + containingClass: ClassNode, + constantValue: Any?, + value: ResolvedValueArgument?, + name: String + ): JCExpression? { if (!isValidIdentifier(name)) return null val args = value?.arguments?.mapNotNull { it.getArgumentExpression() } ?: emptyList() - val expr = convertConstantValueArguments(constantValue, args) ?: return null + val expr = convertConstantValueArguments(containingClass, constantValue, args) ?: return null return treeMaker.Assign(treeMaker.SimpleName(name), expr) } - private fun convertConstantValueArguments(constantValue: Any?, args: List): JCExpression? { + private fun convertConstantValueArguments(containingClass: ClassNode, constantValue: Any?, args: List): JCExpression? { val singleArg = args.singleOrNull() if (constantValue.isOfPrimitiveType()) { @@ -1280,7 +1305,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati } } - return convertLiteralExpression(constantValue) + return convertLiteralExpression(containingClass, constantValue) } private fun tryParseReferenceToIntConstant(expression: KtExpression?): JCExpression? { @@ -1369,20 +1394,22 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati } } - private fun convertLiteralExpression(value: Any?): JCExpression { + private fun convertLiteralExpression(containingClass: ClassNode, value: Any?): JCExpression { + fun convertDeeper(value: Any?) = convertLiteralExpression(containingClass, value) + convertValueOfPrimitiveTypeOrString(value)?.let { return it } return when (value) { null -> treeMaker.Literal(TypeTag.BOT, null) - is ByteArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable()) { convertLiteralExpression(it) }) - is BooleanArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable()) { convertLiteralExpression(it) }) - is CharArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable()) { convertLiteralExpression(it) }) - is ShortArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable()) { convertLiteralExpression(it) }) - is IntArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable()) { convertLiteralExpression(it) }) - is LongArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable()) { convertLiteralExpression(it) }) - is FloatArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable()) { convertLiteralExpression(it) }) - is DoubleArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable()) { convertLiteralExpression(it) }) + is ByteArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable(), ::convertDeeper)) + is BooleanArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable(), ::convertDeeper)) + is CharArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable(), ::convertDeeper)) + is ShortArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable(), ::convertDeeper)) + is IntArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable(), ::convertDeeper)) + is LongArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable(), ::convertDeeper)) + is FloatArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable(), ::convertDeeper)) + is DoubleArray -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value.asIterable(), ::convertDeeper)) is Array<*> -> { // Two-element String array for enumerations ([desc, fieldName]) assert(value.size == 2) val enumType = Type.getType(value[0] as String) @@ -1393,10 +1420,13 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati treeMaker.Select(treeMaker.Type(enumType), treeMaker.name(valueName)) } - is List<*> -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value) { convertLiteralExpression(it) }) + is List<*> -> treeMaker.NewArray(null, JavacList.nil(), mapJList(value, ::convertDeeper)) - is Type -> treeMaker.Select(treeMaker.Type(value), treeMaker.name("class")) - is AnnotationNode -> convertAnnotation(value, packageFqName = null, filtered = false)!! + is Type -> { + checkIfValidTypeName(containingClass, value) + treeMaker.Select(treeMaker.Type(value), treeMaker.name("class")) + } + is AnnotationNode -> convertAnnotation(containingClass, value, packageFqName = null, filtered = false)!! else -> throw IllegalArgumentException("Illegal literal expression value: $value (${value::class.java.canonicalName})") } } @@ -1441,6 +1471,30 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati private fun convertKotlinType(type: KotlinType): Type = typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT) + private fun getFileForClass(c: ClassNode): KtFile? = kaptContext.origins[c]?.element?.containingFile as? KtFile + + private fun reportIfIllegalTypeUsage(containingClass: ClassNode, type: Type) { + val file = getFileForClass(containingClass) + importsFromRoot[file]?.let { importsFromRoot -> + val typeName = type.className + if (importsFromRoot.contains(typeName)) { + val msg = "${containingClass.className}: Can't reference type '${typeName}' from default package in Java stub." + if (strictMode) kaptContext.reportKaptError(msg) + else kaptContext.logger.warn(msg) + } + } + } + + private fun collectImportsFromRootPackage(): Map> = + kaptContext.compiledClasses.mapNotNull(::getFileForClass).distinct().map { file -> + val importsFromRoot = + file.importDirectives + .filter { !it.isAllUnder } + .mapNotNull { im -> im.importPath?.fqName?.takeIf { it.isOneSegmentFQN() } } + file to importsFromRoot.mapTo(mutableSetOf()) { it.asString() } + }.toMap() + + } private fun Any?.isOfPrimitiveType(): Boolean = when (this) { diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java index 90cbc6b0d38..da291216b2b 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java @@ -99,6 +99,16 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi runTest("plugins/kapt3/kapt3-compiler/testData/converter/defaultImpls.kt"); } + @TestMetadata("defaultPackage.kt") + public void testDefaultPackage() throws Exception { + runTest("plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.kt"); + } + + @TestMetadata("defaultPackageCorrectErrorTypes.kt") + public void testDefaultPackageCorrectErrorTypes() throws Exception { + runTest("plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.kt"); + } + @TestMetadata("defaultParameterValueOff.kt") public void testDefaultParameterValueOff() throws Exception { runTest("plugins/kapt3/kapt3-compiler/testData/converter/defaultParameterValueOff.kt"); diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/IrClassFileToSourceStubConverterTestGenerated.java b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/IrClassFileToSourceStubConverterTestGenerated.java index 752f8d3aae8..1273f9ded3e 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/IrClassFileToSourceStubConverterTestGenerated.java +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/IrClassFileToSourceStubConverterTestGenerated.java @@ -100,6 +100,16 @@ public class IrClassFileToSourceStubConverterTestGenerated extends AbstractIrCla runTest("plugins/kapt3/kapt3-compiler/testData/converter/defaultImpls.kt"); } + @TestMetadata("defaultPackage.kt") + public void testDefaultPackage() throws Exception { + runTest("plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.kt"); + } + + @TestMetadata("defaultPackageCorrectErrorTypes.kt") + public void testDefaultPackageCorrectErrorTypes() throws Exception { + runTest("plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.kt"); + } + @TestMetadata("defaultParameterValueOff.kt") public void testDefaultParameterValueOff() throws Exception { runTest("plugins/kapt3/kapt3-compiler/testData/converter/defaultParameterValueOff.kt"); diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.kt b/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.kt new file mode 100644 index 00000000000..2aa63e608a1 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.kt @@ -0,0 +1,45 @@ +// STRICT + +//FILE: test/ClassRefAnnotation.java + +package test; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ClassRefAnnotation { + Class[] value(); +} + +//FILE: a.kt + +class RootClass + +class AnotherRootClass + +//FILE: b.kt +package test + +import java.lang.Number as JavaNumber +import RootClass +import AnotherRootClass as Arc + +interface PackedClass { + fun someMethod(): RootClass + fun otherMethod(): JavaNumber + fun oneMoreMethod(): Arc +} + +@ClassRefAnnotation(RootClass::class) +class PackedWithAnnotation + +// EXPECTED_ERROR(kotlin:11:5) cannot find symbol +// EXPECTED_ERROR(kotlin:14:1) cannot find symbol +// EXPECTED_ERROR(kotlin:9:5) cannot find symbol +// EXPECTED_ERROR(other:-1:-1) test.PackedClass: Can't reference type 'RootClass' from default package in Java stub. +// EXPECTED_ERROR(other:-1:-1) test.PackedClass: Can't reference type 'AnotherRootClass' from default package in Java stub. +// EXPECTED_ERROR(other:-1:-1) test.PackedWithAnnotation: Can't reference type 'RootClass' from default package in Java stub. diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.txt b/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.txt new file mode 100644 index 00000000000..1636b3e06f0 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackage.txt @@ -0,0 +1,72 @@ +import java.lang.System; + +@kotlin.Metadata() +public final class AnotherRootClass { + + public AnotherRootClass() { + super(); + } +} + +//////////////////// + + +import java.lang.System; + +@kotlin.Metadata() +public final class RootClass { + + public RootClass() { + super(); + } +} + +//////////////////// + +package test; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Target(value = {ElementType.TYPE, ElementType.METHOD}) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface ClassRefAnnotation { + + Class[] value(); +} + +//////////////////// + +package test; + +import java.lang.System; + +@kotlin.Metadata() +public abstract interface PackedClass { + + @org.jetbrains.annotations.NotNull() + public abstract RootClass someMethod(); + + @org.jetbrains.annotations.NotNull() + public abstract java.lang.Number otherMethod(); + + @org.jetbrains.annotations.NotNull() + public abstract AnotherRootClass oneMoreMethod(); +} + +//////////////////// + +package test; + +import java.lang.System; + +@kotlin.Metadata() +@ClassRefAnnotation(value = {RootClass.class}) +public final class PackedWithAnnotation { + + public PackedWithAnnotation() { + super(); + } +} diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.kt b/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.kt new file mode 100644 index 00000000000..516a38355ea --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.kt @@ -0,0 +1,46 @@ +// CORRECT_ERROR_TYPES +// STRICT + +//FILE: test/ClassRefAnnotation.java + +package test; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ClassRefAnnotation { + Class[] value(); +} + +//FILE: a.kt + +class RootClass + +class AnotherRootClass + +//FILE: b.kt +package test + +import java.lang.Number as JavaNumber +import RootClass +import AnotherRootClass as Arc + +interface PackedClass { + fun someMethod(): RootClass + fun otherMethod(): JavaNumber + fun oneMoreMethod(): Arc +} + +@ClassRefAnnotation(RootClass::class) +class PackedWithAnnotation + +// EXPECTED_ERROR(kotlin:11:5) cannot find symbol +// EXPECTED_ERROR(kotlin:14:1) cannot find symbol +// EXPECTED_ERROR(kotlin:9:5) cannot find symbol +// EXPECTED_ERROR(other:-1:-1) test.PackedClass: Can't reference type 'RootClass' from default package in Java stub. +// EXPECTED_ERROR(other:-1:-1) test.PackedClass: Can't reference type 'AnotherRootClass' from default package in Java stub. +// EXPECTED_ERROR(other:-1:-1) test.PackedWithAnnotation: Can't reference type 'RootClass' from default package in Java stub. diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.txt b/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.txt new file mode 100644 index 00000000000..7d444abd084 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/defaultPackageCorrectErrorTypes.txt @@ -0,0 +1,72 @@ +import java.lang.System; + +@kotlin.Metadata() +public final class AnotherRootClass { + + public AnotherRootClass() { + super(); + } +} + +//////////////////// + + +import java.lang.System; + +@kotlin.Metadata() +public final class RootClass { + + public RootClass() { + super(); + } +} + +//////////////////// + +package test; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Target(value = {ElementType.TYPE, ElementType.METHOD}) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface ClassRefAnnotation { + + Class[] value(); +} + +//////////////////// + +package test; + +import java.lang.Number; + +@kotlin.Metadata() +public abstract interface PackedClass { + + @org.jetbrains.annotations.NotNull() + public abstract RootClass someMethod(); + + @org.jetbrains.annotations.NotNull() + public abstract java.lang.Number otherMethod(); + + @org.jetbrains.annotations.NotNull() + public abstract AnotherRootClass oneMoreMethod(); +} + +//////////////////// + +package test; + +import java.lang.Number; + +@kotlin.Metadata() +@ClassRefAnnotation(value = {RootClass.class}) +public final class PackedWithAnnotation { + + public PackedWithAnnotation() { + super(); + } +} From 275fef94fe6762c22e388a2f6461a0c049b408db Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Mon, 8 Feb 2021 22:49:45 +0100 Subject: [PATCH 033/153] JVM_IR. Do not mangle callable reference constructor call #KT-44703 Fixed --- .../codegen/FirBlackBoxCodegenTestGenerated.java | 6 ++++++ .../MemoizedInlineClassReplacements.kt | 3 ++- .../inlineClasses/constructorCallableReference.kt | 14 ++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/IrBlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/LightAnalysisModeTestGenerated.java | 5 +++++ .../semantics/IrJsCodegenBoxES6TestGenerated.java | 5 +++++ .../ir/semantics/IrJsCodegenBoxTestGenerated.java | 5 +++++ .../test/semantics/JsCodegenBoxTestGenerated.java | 5 +++++ .../semantics/IrCodegenBoxWasmTestGenerated.java | 5 +++++ 10 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index e7801da77da..483e39195d3 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -16960,6 +16960,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @Test + @TestMetadata("constructorCallableReference.kt") + public void testConstructorCallableReference() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt"); + } + @Test @TestMetadata("constructorImplVisibility.kt") public void testConstructorImplVisibility() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt index 629179bf7c9..5f85b89f619 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt @@ -59,7 +59,8 @@ class MemoizedInlineClassReplacements( it.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA || (it.origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR && it.visibility == DescriptorVisibilities.LOCAL) || it.isStaticInlineClassReplacement || - it.origin.isSynthetic -> + it.origin.isSynthetic || + it.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE -> null it.isInlineClassFieldGetter -> diff --git a/compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt b/compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt new file mode 100644 index 00000000000..816ed49a63b --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt @@ -0,0 +1,14 @@ +// WITH_RUNTIME +// KJS_FULL_RUNTIME + +interface I { + companion object { + val default: IC by lazy(::IC) + } +} + +inline class IC(val ok: String = "OK") : I + +fun box(): String { + return I.default.ok +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index e9208134610..881b0294160 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -16960,6 +16960,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @Test + @TestMetadata("constructorCallableReference.kt") + public void testConstructorCallableReference() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt"); + } + @Test @TestMetadata("constructorImplVisibility.kt") public void testConstructorImplVisibility() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index d0cbbdb125c..fe98e42f7e8 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -16960,6 +16960,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @Test + @TestMetadata("constructorCallableReference.kt") + public void testConstructorCallableReference() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt"); + } + @Test @TestMetadata("constructorImplVisibility.kt") public void testConstructorImplVisibility() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index acb06b859ba..e970f3d16d1 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -14134,6 +14134,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorCallableReference.kt") + public void testConstructorCallableReference() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt"); + } + @TestMetadata("constructorImplVisibility.kt") public void testConstructorImplVisibility() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/constructorImplVisibility.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 36e343d0123..576fd3cbf45 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -12389,6 +12389,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorCallableReference.kt") + public void testConstructorCallableReference() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index a90c4995b66..b57b4501bcc 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -11874,6 +11874,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorCallableReference.kt") + public void testConstructorCallableReference() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 1c1d05da831..42e581345c0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -11939,6 +11939,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorCallableReference.kt") + public void testConstructorCallableReference() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index f1673cf96e0..d0369ce3b16 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -6370,6 +6370,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); } + @TestMetadata("constructorCallableReference.kt") + public void testConstructorCallableReference() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); From 8af9ce1e0b65747fe8161532585368a148b7d24d Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Tue, 9 Feb 2021 00:23:51 +0100 Subject: [PATCH 034/153] Minor. Ignore test on WASM --- .../codegen/box/inlineClasses/constructorCallableReference.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt b/compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt index 816ed49a63b..8aa0e078d1c 100644 --- a/compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt +++ b/compiler/testData/codegen/box/inlineClasses/constructorCallableReference.kt @@ -1,5 +1,6 @@ // WITH_RUNTIME // KJS_FULL_RUNTIME +// IGNORE_BACKEND: WASM interface I { companion object { From 5c5fb0ae39fd522613f45447e536f4548eeca855 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Thu, 4 Feb 2021 19:00:40 +0100 Subject: [PATCH 035/153] Add JvmTarget6OnJvm8 test suite --- compiler/tests-different-jdk/build.gradle.kts | 14 ++++++-------- .../codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt | 3 +++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/tests-different-jdk/build.gradle.kts b/compiler/tests-different-jdk/build.gradle.kts index 54a5604d756..0d57ee4ccd7 100644 --- a/compiler/tests-different-jdk/build.gradle.kts +++ b/compiler/tests-different-jdk/build.gradle.kts @@ -69,25 +69,23 @@ codegenTest(target = 6, jvm = 6, jdk = "JDK_18") { } } +//JDK 8 +codegenTest(target = 6, jvm = 8) {} + +// This is default one and is executed in default build configuration codegenTest(target = 8, jvm = 8) {} -// Switch TC builds to... +//JDK 11 codegenTest(target = 6, jvm = 11) {} codegenTest(target = 8, jvm = 11) {} codegenTest(target = 11, jvm = 11) {} -//...and delete old tasks.. -codegenTest(target = 6, jvm = 9) {} - -codegenTest(target = 8, jvm = 9) {} - -codegenTest(target = 9, jvm = 9) {} - //..also add this two tasks to build after adding fresh jdks to build agents val mostRecentJdk = JdkMajorVersion.values().last().name +//LAST JDK from JdkMajorVersion available on machine codegenTest(target = 6, jvm = "Last", jdk = mostRecentJdk) { jvmArgs!!.add( "-XX:-FailOverToOldVerifier") } diff --git a/compiler/tests-different-jdk/tests/org/jetbrains/kotlin/codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt b/compiler/tests-different-jdk/tests/org/jetbrains/kotlin/codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt index 3cde663b783..b091fea77d4 100644 --- a/compiler/tests-different-jdk/tests/org/jetbrains/kotlin/codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt +++ b/compiler/tests-different-jdk/tests/org/jetbrains/kotlin/codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt @@ -36,6 +36,9 @@ abstract class CustomJvmTargetOnJvmBaseTest @RunWith(JUnitPlatformRunnerForJdk6::class) class JvmTarget6OnJvm6 : CustomJvmTargetOnJvmBaseTest() +@RunWith(JUnitPlatform::class) +class JvmTarget6OnJvm8 : CustomJvmTargetOnJvmBaseTest() + @RunWith(JUnitPlatform::class) class JvmTarget8OnJvm8 : CustomJvmTargetOnJvmBaseTest() From 21e9f67322e61c6ad568c40834c9bc7d0a35b52e Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 5 Feb 2021 07:56:32 +0100 Subject: [PATCH 036/153] Add JvmTargetXOnJvm15 test suites --- build.gradle.kts | 1 + buildSrc/src/main/kotlin/jdksFinder.kt | 4 +-- compiler/tests-different-jdk/build.gradle.kts | 13 ++++++++++ .../jdk/CustomJvmTargetOnJvmBaseTest.kt | 25 +++++++++++-------- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3dc12a70df2..7f1a112ccea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -130,6 +130,7 @@ extra["JDK_18"] = jdkPath("1.8") extra["JDK_9"] = jdkPath("9") extra["JDK_10"] = jdkPath("10") extra["JDK_11"] = jdkPath("11") +extra["JDK_15"] = jdkPath("15") // allow opening the project without setting up all env variables (see KT-26413) if (!kotlinBuildProperties.isInIdeaSync) { diff --git a/buildSrc/src/main/kotlin/jdksFinder.kt b/buildSrc/src/main/kotlin/jdksFinder.kt index 6c2216304e4..3ed259ae7a7 100644 --- a/buildSrc/src/main/kotlin/jdksFinder.kt +++ b/buildSrc/src/main/kotlin/jdksFinder.kt @@ -10,12 +10,12 @@ import net.rubygrapefruit.platform.WindowsRegistry.Key.HKEY_LOCAL_MACHINE import org.gradle.internal.os.OperatingSystem enum class JdkMajorVersion(private val mandatory: Boolean = true) { - JDK_16, JDK_17, JDK_18, JDK_9, JDK_10(false), JDK_11(false); + JDK_16, JDK_17, JDK_18, JDK_9, JDK_10(false), JDK_11(false), /*15.0*/JDK_15(false); fun isMandatory(): Boolean = mandatory } -val jdkAlternativeVarNames = mapOf(JdkMajorVersion.JDK_9 to listOf("JDK_19")) +val jdkAlternativeVarNames = mapOf(JdkMajorVersion.JDK_9 to listOf("JDK_19"), JdkMajorVersion.JDK_15 to listOf("JDK_15_0")) data class JdkId(val explicit: Boolean, val majorVersion: JdkMajorVersion, var version: String, var homeDir: File) diff --git a/compiler/tests-different-jdk/build.gradle.kts b/compiler/tests-different-jdk/build.gradle.kts index 0d57ee4ccd7..5165ec4b32f 100644 --- a/compiler/tests-different-jdk/build.gradle.kts +++ b/compiler/tests-different-jdk/build.gradle.kts @@ -82,6 +82,19 @@ codegenTest(target = 8, jvm = 11) {} codegenTest(target = 11, jvm = 11) {} +//JDK 15 +codegenTest(target = 6, jvm = 15) { + jvmArgs!!.add( "-XX:-FailOverToOldVerifier") +} + +codegenTest(target = 8, jvm = 15) { + jvmArgs!!.add( "-XX:-FailOverToOldVerifier") +} + +codegenTest(target = 15, jvm = 15) { + jvmArgs!!.add( "-XX:-FailOverToOldVerifier") +} + //..also add this two tasks to build after adding fresh jdks to build agents val mostRecentJdk = JdkMajorVersion.values().last().name diff --git a/compiler/tests-different-jdk/tests/org/jetbrains/kotlin/codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt b/compiler/tests-different-jdk/tests/org/jetbrains/kotlin/codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt index b091fea77d4..6c7c072ba39 100644 --- a/compiler/tests-different-jdk/tests/org/jetbrains/kotlin/codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt +++ b/compiler/tests-different-jdk/tests/org/jetbrains/kotlin/codegen/jdk/CustomJvmTargetOnJvmBaseTest.kt @@ -31,17 +31,20 @@ import org.junit.runner.RunWith @UseTechnicalNames abstract class CustomJvmTargetOnJvmBaseTest +// JDK 6 @RunOnlyJdk6Test @Execution(ExecutionMode.SAME_THREAD) @RunWith(JUnitPlatformRunnerForJdk6::class) class JvmTarget6OnJvm6 : CustomJvmTargetOnJvmBaseTest() +// JDK 8 @RunWith(JUnitPlatform::class) class JvmTarget6OnJvm8 : CustomJvmTargetOnJvmBaseTest() @RunWith(JUnitPlatform::class) class JvmTarget8OnJvm8 : CustomJvmTargetOnJvmBaseTest() +// JDK 11 @RunWith(JUnitPlatform::class) class JvmTarget6OnJvm11 : CustomJvmTargetOnJvmBaseTest() @@ -51,6 +54,17 @@ class JvmTarget8OnJvm11 : CustomJvmTargetOnJvmBaseTest() @RunWith(JUnitPlatform::class) class JvmTarget11OnJvm11 : CustomJvmTargetOnJvmBaseTest() +// JDK 15 +@RunWith(JUnitPlatform::class) +class JvmTarget6OnJvm15 : CustomJvmTargetOnJvmBaseTest() + +@RunWith(JUnitPlatform::class) +class JvmTarget8OnJvm15 : CustomJvmTargetOnJvmBaseTest() + +@RunWith(JUnitPlatform::class) +class JvmTarget15OnJvm15 : CustomJvmTargetOnJvmBaseTest() + +// LAST JDK from JdkMajorVersion available on machine @RunWith(JUnitPlatform::class) class JvmTarget6OnJvmLast : CustomJvmTargetOnJvmBaseTest() @@ -59,14 +73,3 @@ class JvmTarget8OnJvmLast : CustomJvmTargetOnJvmBaseTest() @RunWith(JUnitPlatform::class) class JvmTargetLastOnJvmLast : CustomJvmTargetOnJvmBaseTest() - -//TODO: delete old tasks -@RunWith(JUnitPlatform::class) -class JvmTarget6OnJvm9 : CustomJvmTargetOnJvmBaseTest() - -@RunWith(JUnitPlatform::class) -class JvmTarget8OnJvm9 : CustomJvmTargetOnJvmBaseTest() - -@RunWith(JUnitPlatform::class) -class JvmTarget9OnJvm9 : CustomJvmTargetOnJvmBaseTest() - From 3dff225b98302631a46d43b1fa4024023bf29df7 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 5 Feb 2021 14:12:38 +0100 Subject: [PATCH 037/153] Aligh test data with JDK 15 reflection output --- .../box/annotations/syntheticMethodForProperty.kt | 2 +- .../annotations/useTypeParameterAnnotationFromJava.kt | 6 +++--- .../box/annotations/useTypeUseAnnotationFromJava.kt | 10 ++++++---- .../annotations/classLiteralWithVoidDefault.kt | 4 ++-- .../codegen/box/reflection/builtins/enumNameOrdinal.kt | 3 ++- .../codegen/box/reflection/genericSignature/kt11121.kt | 6 ++++-- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/compiler/testData/codegen/box/annotations/syntheticMethodForProperty.kt b/compiler/testData/codegen/box/annotations/syntheticMethodForProperty.kt index e61db0ef6ba..925a11aee8c 100644 --- a/compiler/testData/codegen/box/annotations/syntheticMethodForProperty.kt +++ b/compiler/testData/codegen/box/annotations/syntheticMethodForProperty.kt @@ -32,7 +32,7 @@ fun check(clazz: Class<*>, expected: Boolean = true) { assertTrue(Modifier.isStatic(method.modifiers)) assertTrue(Modifier.isPublic(method.modifiers)) val str = method.declaredAnnotations.single().toString() - assertTrue("@test.Anno\\(value=\"?OK\"?\\)".toRegex().matches(str), str) + assertTrue("@test.Anno\\((value=)?\"?OK\"?\\)".toRegex().matches(str), str) return } } diff --git a/compiler/testData/codegen/box/annotations/useTypeParameterAnnotationFromJava.kt b/compiler/testData/codegen/box/annotations/useTypeParameterAnnotationFromJava.kt index 1f656d25d54..9866f803646 100644 --- a/compiler/testData/codegen/box/annotations/useTypeParameterAnnotationFromJava.kt +++ b/compiler/testData/codegen/box/annotations/useTypeParameterAnnotationFromJava.kt @@ -9,14 +9,14 @@ public class A<@Anno(1) T> {} // FILE: Anno.kt -import kotlin.test.assertEquals +import kotlin.test.assertTrue @Target(AnnotationTarget.TYPE_PARAMETER) annotation class Anno(val value: Int = 0) fun box(): String { val typeParameter = A::class.java.typeParameters.single() - assertEquals("[@Anno(value=1)]", typeParameter.annotations.toList().toString()) - + val parametertoString = typeParameter.annotations.toList().toString() + assertTrue("\\[@Anno\\((value=)?1\\)\\]".toRegex().matches(parametertoString), parametertoString) return "OK" } diff --git a/compiler/testData/codegen/box/annotations/useTypeUseAnnotationFromJava.kt b/compiler/testData/codegen/box/annotations/useTypeUseAnnotationFromJava.kt index 800fc34202e..969b298b622 100644 --- a/compiler/testData/codegen/box/annotations/useTypeUseAnnotationFromJava.kt +++ b/compiler/testData/codegen/box/annotations/useTypeUseAnnotationFromJava.kt @@ -14,17 +14,19 @@ public class A { // FILE: Anno.kt import java.lang.reflect.AnnotatedParameterizedType -import kotlin.test.assertEquals +import kotlin.test.assertTrue @Target(AnnotationTarget.TYPE) annotation class Anno(val value: Int = 0) fun box(): String { val method = A::class.java.declaredMethods.single() - assertEquals("[@Anno(value=1)]", method.annotatedReturnType.annotations.toList().toString()) - + val methodToString = method.annotatedReturnType.annotations.toList().toString() + assertTrue("\\[@Anno\\((value=)?1\\)\\]".toRegex().matches(methodToString), methodToString) + val parameterType = method.parameters.single().annotatedType as AnnotatedParameterizedType - assertEquals("[@Anno(value=2)]", parameterType.annotatedActualTypeArguments.single().annotations.toList().toString()) + val parameterToString = parameterType.annotatedActualTypeArguments.single().annotations.toList().toString() + assertTrue("\\[@Anno\\((value=)?2\\)\\]".toRegex().matches(parameterToString), parameterToString) return "OK" } diff --git a/compiler/testData/codegen/box/reflection/annotations/classLiteralWithVoidDefault.kt b/compiler/testData/codegen/box/reflection/annotations/classLiteralWithVoidDefault.kt index f3e631af95d..f918b969953 100644 --- a/compiler/testData/codegen/box/reflection/annotations/classLiteralWithVoidDefault.kt +++ b/compiler/testData/codegen/box/reflection/annotations/classLiteralWithVoidDefault.kt @@ -23,7 +23,7 @@ class C { } fun box(): String { - assertTrue("\\[@Anno\\(value=void(\\.class)?\\)\\]".toRegex().matches(C::f1.annotations.toString())) - assertTrue("\\[@Anno\\(value=(class )?java.lang.Void(\\.class)?\\)\\]".toRegex().matches(C::f2.annotations.toString())) + assertTrue("\\[@Anno\\((value=)?void(\\.class)?\\)\\]".toRegex().matches(C::f1.annotations.toString())) + assertTrue("\\[@Anno\\((value=)?(class )?java.lang.Void(\\.class)?\\)\\]".toRegex().matches(C::f2.annotations.toString())) return "OK" } diff --git a/compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt b/compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt index b9e1340b5dc..e53e8fd6cef 100644 --- a/compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt +++ b/compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt @@ -3,11 +3,12 @@ // WITH_REFLECT import kotlin.test.assertEquals +import kotlin.test.assertTrue enum class E { X, Y, Z } fun box(): String { - assertEquals(11, E::class.members.size) + assertTrue(E::class.members.size in 11..12, "" + E::class.members.size) assertEquals("Y", E::name.call(E.Y)) assertEquals(2, E::ordinal.call(E.Z)) return "OK" diff --git a/compiler/testData/codegen/box/reflection/genericSignature/kt11121.kt b/compiler/testData/codegen/box/reflection/genericSignature/kt11121.kt index 3d12e88a93c..4c677b3f486 100644 --- a/compiler/testData/codegen/box/reflection/genericSignature/kt11121.kt +++ b/compiler/testData/codegen/box/reflection/genericSignature/kt11121.kt @@ -19,10 +19,12 @@ interface A> { fun box(): String { val defaultImpls = Class.forName("test.A\$DefaultImpls") val declaredMethod = defaultImpls.getDeclaredMethod("p", A::class.java, Any::class.java) - if (declaredMethod.toGenericString() != "public static T test.A\$DefaultImpls.p(test.A,T)") return "fail 1: ${declaredMethod.toGenericString()}" + if (declaredMethod.toGenericString() != "public static T test.A\$DefaultImpls.p(test.A,T)" && + declaredMethod.toGenericString() != "public static ,T,L> T test.A\$DefaultImpls.p(test.A,T)") return "fail 1: ${declaredMethod.toGenericString()}" val declaredProperty = defaultImpls.getDeclaredMethod("getZ", A::class.java, Any::class.java) - if (declaredProperty.toGenericString() != "public static T test.A\$DefaultImpls.getZ(test.A,T)") return "fail 2: ${declaredProperty.toGenericString()}" + if (declaredProperty.toGenericString() != "public static T test.A\$DefaultImpls.getZ(test.A,T)" && + declaredProperty.toGenericString() != "public static ,T> T test.A\$DefaultImpls.getZ(test.A,T)") return "fail 2: ${declaredProperty.toGenericString()}" return "OK" } From 30b5bfe767e7ff896a4919ee043da540de40bca6 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 5 Feb 2021 14:30:42 +0100 Subject: [PATCH 038/153] Disable D8 checks for `-jvm-target 15` tests --- .../tests/org/jetbrains/kotlin/codegen/D8Checker.java | 5 ++++- compiler/tests-different-jdk/build.gradle.kts | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/D8Checker.java b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/D8Checker.java index 4849709db52..569b6e74a49 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/D8Checker.java +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/D8Checker.java @@ -20,12 +20,14 @@ import java.util.function.Consumer; public class D8Checker { - public static final boolean RUN_D8_CHECKER = true; + public static final boolean RUN_D8_CHECKER = !Boolean.valueOf(System.getProperty("kotlin.test.box.d8.disable")); private D8Checker() { } public static void check(ClassFileFactory outputFiles) { + if (!RUN_D8_CHECKER) return; + runD8(builder -> { for (OutputFile file : ClassFileUtilsKt.getClassFiles(outputFiles)) { byte[] bytes = file.asByteArray(); @@ -35,6 +37,7 @@ public class D8Checker { } public static void checkFilesWithD8(Collection> classFiles) { + if (!RUN_D8_CHECKER) return; runD8(builder -> { classFiles.forEach(pair -> { builder.addClassProgramData(pair.getFirst(), new PathOrigin(Paths.get(pair.getSecond()))); diff --git a/compiler/tests-different-jdk/build.gradle.kts b/compiler/tests-different-jdk/build.gradle.kts index 5165ec4b32f..80fe18fe35a 100644 --- a/compiler/tests-different-jdk/build.gradle.kts +++ b/compiler/tests-different-jdk/build.gradle.kts @@ -93,6 +93,7 @@ codegenTest(target = 8, jvm = 15) { codegenTest(target = 15, jvm = 15) { jvmArgs!!.add( "-XX:-FailOverToOldVerifier") + systemProperty("kotlin.test.box.d8.disable", true) } //..also add this two tasks to build after adding fresh jdks to build agents @@ -112,6 +113,9 @@ codegenTest( targetInTestClass = "Last", jvm = "Last", jdk = mostRecentJdk -) {} +) { + jvmArgs!!.add( "-XX:-FailOverToOldVerifier") + systemProperty("kotlin.test.box.d8.disable", true) +} testsJar() From 2b088f1147578c32f1a433ccfd506eaafdc021d8 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Mon, 8 Feb 2021 11:04:03 +0300 Subject: [PATCH 039/153] [FIR] Fix generating data class if there is non-property in primary constructor #KT-44554 Fixed --- ...otTouchedTilContractsPhaseTestGenerated.java | 5 +++++ .../testData/resolve/incorrectDataClass.fir.txt | 17 +++++++++++++++++ .../testData/resolve/incorrectDataClass.kt | 5 +++++ .../runners/FirDiagnosticTestGenerated.java | 6 ++++++ ...irDiagnosticsWithLightTreeTestGenerated.java | 6 ++++++ .../kotlin/fir/builder/RawFirBuilder.kt | 6 ++---- 6 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 698661d6ac2..bde3f0cf9ec 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -244,6 +244,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt"); } + @TestMetadata("incorrectDataClass.kt") + public void testIncorrectDataClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt"); + } + @TestMetadata("incorrectSuperCall.kt") public void testIncorrectSuperCall() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/incorrectSuperCall.kt"); diff --git a/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.fir.txt new file mode 100644 index 00000000000..7ba603cf38d --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.fir.txt @@ -0,0 +1,17 @@ +FILE: incorrectDataClass.kt + public final data class Foo : R|kotlin/Any| { + public constructor(a: R|kotlin/Int|, b: R|kotlin/Int|): R|Foo| { + super() + } + + public final val b: R|kotlin/Int| = R|/b| + public get(): R|kotlin/Int| + + public final val c: R|kotlin/Int| = Int(4) + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/Int| + + public final fun copy(b: R|kotlin/Int| = this@R|/Foo|.R|/Foo.b|): R|Foo| + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt b/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt new file mode 100644 index 00000000000..214fca2b270 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt @@ -0,0 +1,5 @@ +// ISSUE: KT-44554 + +data class Foo(a: Int, val b: Int) { + val c = 4 +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 92d29a5322b..9b2a3b940cd 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -284,6 +284,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt"); } + @Test + @TestMetadata("incorrectDataClass.kt") + public void testIncorrectDataClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt"); + } + @Test @TestMetadata("incorrectSuperCall.kt") public void testIncorrectSuperCall() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 931d3a4966f..f7ad4f2e209 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -287,6 +287,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.kt"); } + @Test + @TestMetadata("incorrectDataClass.kt") + public void testIncorrectDataClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/incorrectDataClass.kt"); + } + @Test @TestMetadata("incorrectSuperCall.kt") public void testIncorrectSuperCall() throws Exception { diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 3959e85a96a..214134975b2 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -862,9 +862,7 @@ class RawFirBuilder( } if (classOrObject.hasModifier(DATA_KEYWORD) && firPrimaryConstructor != null) { - val zippedParameters = classOrObject.primaryConstructorParameters.zip( - declarations.filterIsInstance(), - ) + val zippedParameters = classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() } zip declarations.filterIsInstance() DataClassMembersGenerator( baseSession, classOrObject, @@ -877,7 +875,7 @@ class RawFirBuilder( // just making a shallow copy isn't enough type ref may be a function type ref // and contain value parameters inside withDefaultSourceElementKind(newKind) { - (property.returnTypeRef.psi as KtTypeReference).toFirOrImplicitType() + (property.returnTypeRef.psi as KtTypeReference?).toFirOrImplicitType() } }, ).generate() From 9724d81a4995879cc1335d53dde168592aecbd18 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Mon, 8 Feb 2021 11:26:36 +0300 Subject: [PATCH 040/153] [FIR] Support boolean elvis bound smartcasts #KT-44511 Fixed --- ...TouchedTilContractsPhaseTestGenerated.java | 5 +++ .../booleanElvisBoundSmartcast.fir.txt | 35 +++++++++++++++++++ .../booleans/booleanElvisBoundSmartcast.kt | 22 ++++++++++++ .../runners/FirDiagnosticTestGenerated.java | 6 ++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++++ .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 22 ++++++++++-- ...ControlFlowStatementsResolveTransformer.kt | 2 +- .../tests/smartCasts/elvis/basicOn.fir.kt | 6 ++-- 8 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.kt diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index bde3f0cf9ec..24546bf8cde 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -2818,6 +2818,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @TestMetadata("booleanElvisBoundSmartcast.kt") + public void testBooleanElvisBoundSmartcast() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.kt"); + } + @TestMetadata("booleanOperators.kt") public void testBooleanOperators() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanOperators.kt"); diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.fir.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.fir.txt new file mode 100644 index 00000000000..2429c056d0f --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.fir.txt @@ -0,0 +1,35 @@ +FILE: booleanElvisBoundSmartcast.kt + public final class A : R|kotlin/Any| { + public constructor(b: R|kotlin/Boolean|): R|A| { + super() + } + + public final val b: R|kotlin/Boolean| = R|/b| + public get(): R|kotlin/Boolean| + + public final fun foo(): R|kotlin/Unit| { + } + + } + public final fun test_1(a: R|A?|): R|kotlin/Unit| { + when () { + R|/a|?.{ $subj$.R|/A.b| } ?: Boolean(false) -> { + R|/a|.R|/A.foo|() + } + else -> { + R|/a|.#() + } + } + + } + public final fun test_2(a: R|A?|): R|kotlin/Unit| { + when () { + R|/a|?.{ $subj$.R|/A.b| } ?: Boolean(true) -> { + R|/a|.#() + } + else -> { + R|/a|.R|/A.foo|() + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.kt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.kt new file mode 100644 index 00000000000..f7e4d049fc3 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +BooleanElvisBoundSmartCasts +// ISSUE: KT-44511, also relates to KT-8492 and KT-26357 + +class A(val b: Boolean) { + fun foo() {} +} + +fun test_1(a: A?) { + if (a?.b ?: false) { + a.foo() // OK + } else { + a.foo() // Error + } +} + +fun test_2(a: A?) { + if (a?.b ?: true) { + a.foo() // Error + } else { + a.foo() // OK + } +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 9b2a3b940cd..8b9c3797d72 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -3194,6 +3194,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("booleanElvisBoundSmartcast.kt") + public void testBooleanElvisBoundSmartcast() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.kt"); + } + @Test @TestMetadata("booleanOperators.kt") public void testBooleanOperators() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index f7ad4f2e209..04ec51b634d 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -3229,6 +3229,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("booleanElvisBoundSmartcast.kt") + public void testBooleanElvisBoundSmartcast() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans/booleanElvisBoundSmartcast.kt"); + } + @Test @TestMetadata("booleanOperators.kt") public void testBooleanOperators() 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 e9e965b1d18..84b0db2b66d 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.resolve.dfa +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.PrivateForInline import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription @@ -14,6 +15,7 @@ import org.jetbrains.kotlin.fir.contracts.description.ConeConstantReference import org.jetbrains.kotlin.fir.contracts.description.ConeReturnsEffectDeclaration import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack @@ -26,6 +28,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBod import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.name.FqName @@ -1123,8 +1126,23 @@ abstract class FirDataFlowAnalyzer( } } - fun exitElvis() { - graphBuilder.exitElvis().mergeIncomingFlow() + fun exitElvis(elvisExpression: FirElvisExpression) { + val node = graphBuilder.exitElvis().mergeIncomingFlow() + if (!components.session.languageVersionSettings.supportsFeature(LanguageFeature.BooleanElvisBoundSmartCasts)) return + val lhs = elvisExpression.lhs + val rhs = elvisExpression.rhs + if (rhs is FirConstExpression<*> && rhs.kind == ConstantValueKind.Boolean) { + if (lhs.typeRef.coneType.classId != StandardClassIds.Boolean) return + + val flow = node.flow + // a ?: false == true -> a != null + // a ?: true == false -> a != null + val elvisVariable = variableStorage.getOrCreateVariable(flow, elvisExpression) + val lhsVariable = variableStorage.getOrCreateVariable(flow, lhs) + + val value = rhs.value as Boolean + flow.addImplication(elvisVariable.eq(!value) implies (lhsVariable.notEq(null))) + } } // Callable reference diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt index 00ab34356f2..57fb8188b3c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt @@ -244,7 +244,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran } } - dataFlowAnalyzer.exitElvis() + dataFlowAnalyzer.exitElvis(elvisExpression) return result.compose() } } diff --git a/compiler/testData/diagnostics/tests/smartCasts/elvis/basicOn.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/elvis/basicOn.fir.kt index 89029fb6fd7..dacb3b62b03 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/elvis/basicOn.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/elvis/basicOn.fir.kt @@ -11,13 +11,13 @@ interface Order { fun foo(o: Any) { val order = o as? Order if (order?.expired ?: false) { - order.doSomething() + order.doSomething() } else { } if (order?.notExpired() ?: false) { - order.doSomething() + order.doSomething() } } @@ -47,4 +47,4 @@ fun baz(o: Boolean?) { else { o.hashCode() } -} \ No newline at end of file +} From 6f9bcf249b0305edbfe7b3f68f747865baba496d Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Tue, 9 Feb 2021 13:07:15 +0500 Subject: [PATCH 041/153] [IR] Supported inlining of adapted references + tests --- ...FirBlackBoxInlineCodegenTestGenerated.java | 40 +++ .../common/lower/inline/FunctionInlining.kt | 228 ++++++++++-------- .../adaptedReferences/inlineBound.kt | 17 ++ .../adaptedReferences/inlineDefault.kt | 19 ++ .../adaptedReferences/inlineVararg.kt | 20 ++ .../inlineVarargAndDefault.kt | 14 ++ .../adaptedReferences/inlineVarargInts.kt | 18 ++ .../BlackBoxInlineCodegenTestGenerated.java | 40 +++ ...otlinAgainstInlineKotlinTestGenerated.java | 40 +++ .../IrBlackBoxInlineCodegenTestGenerated.java | 40 +++ ...otlinAgainstInlineKotlinTestGenerated.java | 40 +++ ...JvmIrAgainstOldBoxInlineTestGenerated.java | 40 +++ ...JvmOldAgainstIrBoxInlineTestGenerated.java | 40 +++ .../IrJsCodegenInlineES6TestGenerated.java | 38 +++ .../IrJsCodegenInlineTestGenerated.java | 38 +++ .../JsCodegenInlineTestGenerated.java | 38 +++ 16 files changed, 603 insertions(+), 107 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt create mode 100644 compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt create mode 100644 compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt create mode 100644 compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt create mode 100644 compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java index 78cc475b292..c9b99edc41d 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java @@ -1020,6 +1020,46 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + public class AdaptedReferences { + @Test + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @Test + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @Test + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @Test + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @Test + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt index 1a29f8e91c9..0691b6792c5 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt @@ -225,8 +225,6 @@ class FunctionInlining( else (copyIrElement.copy(argument) as IrExpression) } - //-----------------------------------------------------------------// - override fun visitCall(expression: IrCall): IrExpression { if (!isLambdaCall(expression)) return super.visitCall(expression) @@ -236,119 +234,133 @@ class FunctionInlining( if ((dispatchReceiver.symbol.owner as? IrValueParameter)?.isNoinline == true) return super.visitCall(expression) - if (functionArgument is IrFunctionReference) { - functionArgument.transformChildrenVoid(this) - - val function = functionArgument.symbol.owner - val functionParameters = function.explicitParameters - val boundFunctionParameters = functionArgument.getArgumentsWithIr() - val unboundFunctionParameters = functionParameters - boundFunctionParameters.map { it.first } - val boundFunctionParametersMap = boundFunctionParameters.associate { it.first to it.second } - - var unboundIndex = 0 - val unboundArgsSet = unboundFunctionParameters.toSet() - val valueParameters = expression.getArgumentsWithIr().drop(1) // Skip dispatch receiver. - - val superType = functionArgument.type as IrSimpleType - val superTypeArgumentsMap = expression.symbol.owner.parentAsClass.typeParameters.associate { typeParam -> - typeParam.symbol to superType.arguments[typeParam.index].typeOrNull!! - } - - val immediateCall = with(expression) { - when (function) { - is IrConstructor -> { - val classTypeParametersCount = function.parentAsClass.typeParameters.size - IrConstructorCallImpl.fromSymbolOwner( - startOffset, - endOffset, - function.returnType, - function.symbol, - classTypeParametersCount - ) - } - is IrSimpleFunction -> - IrCallImpl( - startOffset, - endOffset, - function.returnType, - function.symbol, - function.typeParameters.size, - function.valueParameters.size - ) - else -> - error("Unknown function kind : ${function.render()}") - } - }.apply { - for (parameter in functionParameters) { - val argument = - if (parameter !in unboundArgsSet) { - val arg = boundFunctionParametersMap[parameter]!! - if (arg is IrGetValueWithoutLocation) - arg.withLocation(expression.startOffset, expression.endOffset) - else arg - } else { - if (unboundIndex == valueParameters.size && parameter.defaultValue != null) - copyIrElement.copy(parameter.defaultValue!!.expression) as IrExpression - else if (!parameter.isVararg) { - assert(unboundIndex < valueParameters.size) { - "Attempt to use unbound parameter outside of the callee's value parameters" - } - valueParameters[unboundIndex++].second - } else { - val elements = mutableListOf() - while (unboundIndex < valueParameters.size) { - val (param, value) = valueParameters[unboundIndex++] - val substitutedParamType = param.type.substitute(superTypeArgumentsMap) - if (substitutedParamType == parameter.varargElementType!!) - elements += value - else - elements += IrSpreadElementImpl(expression.startOffset, expression.endOffset, value) - } - IrVarargImpl( - expression.startOffset, expression.endOffset, - parameter.type, - parameter.varargElementType!!, - elements - ) - } - } - when (parameter) { - function.dispatchReceiverParameter -> - this.dispatchReceiver = argument.implicitCastIfNeededTo(function.dispatchReceiverParameter!!.type) - - function.extensionReceiverParameter -> - this.extensionReceiver = argument.implicitCastIfNeededTo(function.extensionReceiverParameter!!.type) - - else -> - putValueArgument( - parameter.index, - argument.implicitCastIfNeededTo(function.valueParameters[parameter.index].type) - ) - } - } - assert(unboundIndex == valueParameters.size) { "Not all arguments of the callee are used" } - for (index in 0 until functionArgument.typeArgumentsCount) - putTypeArgument(index, functionArgument.getTypeArgument(index)) - }.implicitCastIfNeededTo(expression.type) - return this@FunctionInlining.visitExpression(super.visitExpression(immediateCall)) + return when { + functionArgument is IrFunctionReference -> inlineFunctionReference(expression, functionArgument) + functionArgument.isAdaptedFunctionReference() -> inlineAdaptedFunctionReference(expression, functionArgument as IrBlock) + functionArgument is IrFunctionExpression -> inlineFunctionExpression(expression, functionArgument) + else -> super.visitCall(expression) } - if (functionArgument !is IrFunctionExpression) - return super.visitCall(expression) + } + fun inlineFunctionExpression(irCall: IrCall, irFunctionExpression: IrFunctionExpression): IrExpression { // Inline the lambda. Lambda parameters will be substituted with lambda arguments. val newExpression = inlineFunction( - expression, - functionArgument.function, + irCall, + irFunctionExpression.function, false ) // Substitute lambda arguments with target function arguments. - return newExpression.transform( - this, - null + return newExpression.transform(this, null) + } + + fun inlineAdaptedFunctionReference(irCall: IrCall, irBlock: IrBlock): IrExpression { + val irFunction = irBlock.statements[0] as IrFunction + irFunction.transformChildrenVoid(this) + val irFunctionReference = irBlock.statements[1] as IrFunctionReference + val inlinedFunctionReference = inlineFunctionReference(irCall, irFunctionReference) + return IrBlockImpl( + irCall.startOffset, irCall.endOffset, + inlinedFunctionReference.type, origin = null, + statements = listOf(irFunction, inlinedFunctionReference) ) } - //-----------------------------------------------------------------// + fun inlineFunctionReference(irCall: IrCall, irFunctionReference: IrFunctionReference): IrExpression { + irFunctionReference.transformChildrenVoid(this) + + val function = irFunctionReference.symbol.owner + val functionParameters = function.explicitParameters + val boundFunctionParameters = irFunctionReference.getArgumentsWithIr() + val unboundFunctionParameters = functionParameters - boundFunctionParameters.map { it.first } + val boundFunctionParametersMap = boundFunctionParameters.associate { it.first to it.second } + + var unboundIndex = 0 + val unboundArgsSet = unboundFunctionParameters.toSet() + val valueParameters = irCall.getArgumentsWithIr().drop(1) // Skip dispatch receiver. + + val superType = irFunctionReference.type as IrSimpleType + val superTypeArgumentsMap = irCall.symbol.owner.parentAsClass.typeParameters.associate { typeParam -> + typeParam.symbol to superType.arguments[typeParam.index].typeOrNull!! + } + + val immediateCall = with(irCall) { + when (function) { + is IrConstructor -> { + val classTypeParametersCount = function.parentAsClass.typeParameters.size + IrConstructorCallImpl.fromSymbolOwner( + startOffset, + endOffset, + function.returnType, + function.symbol, + classTypeParametersCount + ) + } + is IrSimpleFunction -> + IrCallImpl( + startOffset, + endOffset, + function.returnType, + function.symbol, + function.typeParameters.size, + function.valueParameters.size + ) + else -> + kotlin.error("Unknown function kind : ${function.render()}") + } + }.apply { + for (parameter in functionParameters) { + val argument = + if (parameter !in unboundArgsSet) { + val arg = boundFunctionParametersMap[parameter]!! + if (arg is IrGetValueWithoutLocation) + arg.withLocation(irCall.startOffset, irCall.endOffset) + else arg + } else { + if (unboundIndex == valueParameters.size && parameter.defaultValue != null) + copyIrElement.copy(parameter.defaultValue!!.expression) as IrExpression + else if (!parameter.isVararg) { + assert(unboundIndex < valueParameters.size) { + "Attempt to use unbound parameter outside of the callee's value parameters" + } + valueParameters[unboundIndex++].second + } else { + val elements = mutableListOf() + while (unboundIndex < valueParameters.size) { + val (param, value) = valueParameters[unboundIndex++] + val substitutedParamType = param.type.substitute(superTypeArgumentsMap) + if (substitutedParamType == parameter.varargElementType!!) + elements += value + else + elements += IrSpreadElementImpl(irCall.startOffset, irCall.endOffset, value) + } + IrVarargImpl( + irCall.startOffset, irCall.endOffset, + parameter.type, + parameter.varargElementType!!, + elements + ) + } + } + when (parameter) { + function.dispatchReceiverParameter -> + this.dispatchReceiver = argument.implicitCastIfNeededTo(function.dispatchReceiverParameter!!.type) + + function.extensionReceiverParameter -> + this.extensionReceiver = argument.implicitCastIfNeededTo(function.extensionReceiverParameter!!.type) + + else -> + putValueArgument( + parameter.index, + argument.implicitCastIfNeededTo(function.valueParameters[parameter.index].type) + ) + } + } + assert(unboundIndex == valueParameters.size) { "Not all arguments of the callee are used" } + for (index in 0 until irFunctionReference.typeArgumentsCount) + putTypeArgument(index, irFunctionReference.getTypeArgument(index)) + }.implicitCastIfNeededTo(irCall.type) + return this@FunctionInlining.visitExpression(super.visitExpression(immediateCall)) + } override fun visitElement(element: IrElement) = element.accept(this, null) } @@ -369,7 +381,8 @@ class FunctionInlining( && irCall.dispatchReceiver is IrGetValue } - //-------------------------------------------------------------------------// + private fun IrExpression.isAdaptedFunctionReference() = + this is IrBlock && this.origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE private inner class ParameterToArgument( val parameter: IrValueParameter, @@ -379,7 +392,8 @@ class FunctionInlining( val isInlinableLambdaArgument: Boolean get() = parameter.isInlineParameter() && (argumentExpression is IrFunctionReference - || argumentExpression is IrFunctionExpression) + || argumentExpression is IrFunctionExpression + || argumentExpression.isAdaptedFunctionReference()) val isImmutableVariableLoad: Boolean get() = argumentExpression.let { argument -> diff --git a/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt new file mode 100644 index 00000000000..f381f4f6c99 --- /dev/null +++ b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt @@ -0,0 +1,17 @@ +// DONT_TARGET_EXACT_BACKEND: WASM +// WASM_MUTE_REASON: BINDING_RECEIVERS + +// FILE: 1.kt +package test + +inline fun foo(x: () -> Unit): String { + x() + return "OK" +} + +inline fun String.id(s: String = this, vararg xs: Int): String = s + +// FILE: 2.kt +import test.* + +fun box(): String = foo("Fail"::id) diff --git a/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt new file mode 100644 index 00000000000..bd8f565ec9a --- /dev/null +++ b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt @@ -0,0 +1,19 @@ +// DONT_TARGET_EXACT_BACKEND: WASM +// WASM_MUTE_REASON: STDLIB_TEXT +// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType +// WITH_RUNTIME +// KJS_WITH_FULL_RUNTIME + +// FILE: 1.kt +package test + +inline fun foo(mkString: () -> String): String = + mkString() + +inline fun bar (xs: CharArray = charArrayOf('O','K')) = + String(xs) + +// FILE: 2.kt +import test.* + +fun box(): String = foo(::bar) diff --git a/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt new file mode 100644 index 00000000000..eb009f99f26 --- /dev/null +++ b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt @@ -0,0 +1,20 @@ +// DONT_TARGET_EXACT_BACKEND: WASM +// WASM_MUTE_REASON: IGNORED_IN_JS +// !LANGUAGE: +NewInference + +// FILE: 1.kt +package test + +inline fun foo(f: (Int, Int) -> Int): Int = + f(42, 117) + +inline fun bar (vararg xs: Int): Int { + var sum = 0 + for (x in xs) sum += x + return sum +} + +// FILE: 2.kt +import test.* + +fun box(): String = if (foo(::bar) == 159) "OK" else "fail" diff --git a/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt new file mode 100644 index 00000000000..f3e286ce301 --- /dev/null +++ b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt @@ -0,0 +1,14 @@ +// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType + +// FILE: 1.kt +package test + +inline fun foo(vararg l: Long, s: String = "OK"): String = + if (l.size == 0) s else "Fail" + +inline fun bar(f: () -> String): String = f() + +// FILE: 2.kt +import test.* + +fun box(): String = bar(::foo) diff --git a/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt new file mode 100644 index 00000000000..58f41020c96 --- /dev/null +++ b/compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt @@ -0,0 +1,18 @@ +// !LANGUAGE: +NewInference +// WITH_RUNTIME +// KJS_WITH_FULL_RUNTIME + +// FILE: 1.kt +package test + +inline fun foo(x: (Int, Int) -> Int): Int = + x(120,3) + +inline fun bar(vararg x: Int): Int = + x.sum() + +// FILE: 2.kt +import test.* + +fun box(): String = + if (foo(::bar) == 123) "OK" else "FAIL" diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java index f080a1b5d6e..72138fbfd89 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -1020,6 +1020,46 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + public class AdaptedReferences { + @Test + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @Test + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @Test + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @Test + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @Test + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @Test + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index b5a34bce5e4..d0f0178aca3 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -1020,6 +1020,46 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + public class AdaptedReferences { + @Test + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @Test + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @Test + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @Test + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @Test + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @Test + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java index b27943edb45..58f7c16bd5b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java @@ -1020,6 +1020,46 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + public class AdaptedReferences { + @Test + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @Test + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @Test + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @Test + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @Test + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index 82a9a8ed03d..656b29eb9e4 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -1020,6 +1020,46 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + public class AdaptedReferences { + @Test + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @Test + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @Test + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @Test + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @Test + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java index b33d5bef291..d50581746ff 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java @@ -1020,6 +1020,46 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + public class AdaptedReferences { + @Test + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_IR_AGAINST_OLD, true); + } + + @Test + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @Test + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @Test + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @Test + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @Test + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java index d97680edabe..cb3218d01f0 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java @@ -1020,6 +1020,46 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @Nested + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + public class AdaptedReferences { + @Test + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_OLD_AGAINST_IR, true); + } + + @Test + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @Test + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @Test + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @Test + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @Test + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java index 656a28746bd..7873282c37d 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java @@ -770,6 +770,44 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AdaptedReferences extends AbstractIrJsCodegenInlineES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java index ad8ae8af225..c2eb3216cec 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java @@ -770,6 +770,44 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AdaptedReferences extends AbstractIrJsCodegenInlineTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java index 52adc97aede..16d7521b1f4 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java @@ -770,6 +770,44 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest { runTest("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt"); } + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/adaptedReferences") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AdaptedReferences extends AbstractJsCodegenInlineTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInAdaptedReferences() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/adaptedReferences"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); + } + + @TestMetadata("inlineBound.kt") + public void testInlineBound() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineBound.kt"); + } + + @TestMetadata("inlineDefault.kt") + public void testInlineDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineDefault.kt"); + } + + @TestMetadata("inlineVararg.kt") + public void testInlineVararg() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVararg.kt"); + } + + @TestMetadata("inlineVarargAndDefault.kt") + public void testInlineVarargAndDefault() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargAndDefault.kt"); + } + + @TestMetadata("inlineVarargInts.kt") + public void testInlineVarargInts() throws Exception { + runTest("compiler/testData/codegen/boxInline/callableReference/adaptedReferences/inlineVarargInts.kt"); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) From e3c1aa599d4990232c202af7bf874f6c8ddf5f6a Mon Sep 17 00:00:00 2001 From: Andrei Klunnyi Date: Tue, 9 Feb 2021 12:54:51 +0000 Subject: [PATCH 042/153] KT-44487 [Sealed Interfaces]: sealed-inheritors-provider for MPP --- .../jetbrains/kotlin/frontend/di/injection.kt | 11 ++++--- .../CompositeResolverForModuleFactory.kt | 3 +- .../caches/resolve/PerFileAnalysisCache.kt | 6 ++-- .../IdeSealedClassInheritorsProvider.kt | 32 ++++++++++++++++--- .../idea/project/ResolveElementCache.kt | 5 +-- .../common/common.kt | 7 ++++ .../commonA/commonA.kt | 1 + .../dependencies.txt | 8 +++++ .../platformAX/platformAX.kt | 8 +++++ .../platformAY/platformAY.kt | 8 +++++ .../MultiplatformAnalysisTestGenerated.java | 5 +++ 11 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 idea/testData/multiplatform/whenExhaustivenessForSealed/common/common.kt create mode 100644 idea/testData/multiplatform/whenExhaustivenessForSealed/commonA/commonA.kt create mode 100644 idea/testData/multiplatform/whenExhaustivenessForSealed/dependencies.txt create mode 100644 idea/testData/multiplatform/whenExhaustivenessForSealed/platformAX/platformAX.kt create mode 100644 idea/testData/multiplatform/whenExhaustivenessForSealed/platformAY/platformAY.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt index 68d5d6a23a2..20b936b0438 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt @@ -134,9 +134,10 @@ fun createContainerForBodyResolve( statementFilter: StatementFilter, analyzerServices: PlatformDependentAnalyzerServices, languageVersionSettings: LanguageVersionSettings, - moduleStructureOracle: ModuleStructureOracle + moduleStructureOracle: ModuleStructureOracle, + sealedProvider: SealedClassInheritorsProvider = CliSealedClassInheritorsProvider ): StorageComponentContainer = createContainer("BodyResolve", analyzerServices) { - configureModule(moduleContext, platform, analyzerServices, bindingTrace, languageVersionSettings) + configureModule(moduleContext, platform, analyzerServices, bindingTrace, languageVersionSettings, sealedProvider) useInstance(statementFilter) @@ -156,10 +157,10 @@ fun createContainerForLazyBodyResolve( analyzerServices: PlatformDependentAnalyzerServices, languageVersionSettings: LanguageVersionSettings, moduleStructureOracle: ModuleStructureOracle, - mainFunctionDetectorFactory: MainFunctionDetector.Factory + mainFunctionDetectorFactory: MainFunctionDetector.Factory, + sealedProvider: SealedClassInheritorsProvider = CliSealedClassInheritorsProvider ): StorageComponentContainer = createContainer("LazyBodyResolve", analyzerServices) { - configureModule(moduleContext, platform, analyzerServices, bindingTrace, languageVersionSettings) - + configureModule(moduleContext, platform, analyzerServices, bindingTrace, languageVersionSettings, sealedProvider) useInstance(mainFunctionDetectorFactory) useInstance(kotlinCodeAnalyzer) useInstance(kotlinCodeAnalyzer.fileScopeProvider) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CompositeResolverForModuleFactory.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CompositeResolverForModuleFactory.kt index d6d9fdf7947..ad6528edc56 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CompositeResolverForModuleFactory.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CompositeResolverForModuleFactory.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.frontend.di.configureModule import org.jetbrains.kotlin.frontend.di.configureStandardResolveComponents import org.jetbrains.kotlin.frontend.java.di.configureJavaSpecificComponents import org.jetbrains.kotlin.frontend.java.di.initializeJavaSpecificComponents +import org.jetbrains.kotlin.idea.compiler.IdeSealedClassInheritorsProvider import org.jetbrains.kotlin.idea.configuration.IdeBuiltInsLoadingState import org.jetbrains.kotlin.idea.project.IdeaEnvironment import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver @@ -189,7 +190,7 @@ class CompositeResolverForModuleFactory( } // Called by all normal containers set-ups - configureModule(moduleContext, targetPlatform, analyzerServices, trace, languageVersionSettings,) + configureModule(moduleContext, targetPlatform, analyzerServices, trace, languageVersionSettings, IdeSealedClassInheritorsProvider) configureStandardResolveComponents() useInstance(moduleContentScope) useInstance(declarationProviderFactory) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/PerFileAnalysisCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/PerFileAnalysisCache.kt index 84c206f2acd..dd57d976184 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/PerFileAnalysisCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/PerFileAnalysisCache.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.idea.caches.project.getModuleInfo import org.jetbrains.kotlin.idea.caches.trackers.clearInBlockModifications import org.jetbrains.kotlin.idea.caches.trackers.inBlockModifications import org.jetbrains.kotlin.idea.compiler.IdeMainFunctionDetectorFactory +import org.jetbrains.kotlin.idea.compiler.IdeSealedClassInheritorsProvider import org.jetbrains.kotlin.idea.project.IdeaModuleStructureOracle import org.jetbrains.kotlin.idea.project.findAnalyzerServices import org.jetbrains.kotlin.idea.project.languageVersionSettings @@ -482,8 +483,9 @@ private object KotlinResolveDataProvider { targetPlatform.findAnalyzerServices(project), analyzableElement.languageVersionSettings, IdeaModuleStructureOracle(), - IdeMainFunctionDetectorFactory() - ).get() + IdeMainFunctionDetectorFactory(), + IdeSealedClassInheritorsProvider + ).get() lazyTopDownAnalyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, listOf(analyzableElement)) } finally { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/compiler/IdeSealedClassInheritorsProvider.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/compiler/IdeSealedClassInheritorsProvider.kt index 13fdb4c15d7..e3b068dd23d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/compiler/IdeSealedClassInheritorsProvider.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/compiler/IdeSealedClassInheritorsProvider.kt @@ -5,19 +5,27 @@ package org.jetbrains.kotlin.idea.compiler +import com.intellij.openapi.module.ModuleManager import com.intellij.psi.* import com.intellij.psi.search.* import com.intellij.psi.search.searches.ClassInheritorsSearch import com.intellij.psi.search.searches.ClassInheritorsSearch.SearchParameters +import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.codegen.JvmCodegenUtil import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.containingPackage +import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors import org.jetbrains.kotlin.idea.caches.resolve.util.javaResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.util.resolveToDescriptor import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade +import org.jetbrains.kotlin.types.typeUtil.closure object IdeSealedClassInheritorsProvider : SealedClassInheritorsProvider() { @@ -29,18 +37,28 @@ object IdeSealedClassInheritorsProvider : SealedClassInheritorsProvider() { val sealedKtClass = sealedClass.findPsi() as? KtClass ?: return emptyList() val searchScope: SearchScope = if (allowSealedInheritorsInDifferentFilesOfSamePackage) { val module = sealedKtClass.module ?: return emptyList() - val moduleSourceScope = GlobalSearchScope.moduleScope(module) + val moduleManager = ModuleManager.getInstance(sealedKtClass.project) + + val modulesScope = sealedClass.module.listCommonModulesIfAny().toMutableList() + .apply { add(sealedClass.module) } + .mapNotNull { moduleManager.findModuleByName(JvmCodegenUtil.getModuleName(it))?.moduleScope } + + val mppAwareSearchScope = GlobalSearchScope.union(modulesScope) + val containingPackage = sealedClass.containingPackage() ?: return emptyList() - val psiPackage = getPackageViaDirectoryService(sealedKtClass) - ?: JavaPsiFacade.getInstance(sealedKtClass.project).findPackage(containingPackage.asString()) + val psiPackage = KotlinJavaPsiFacade.getInstance(sealedKtClass.project) + .findPackage(containingPackage.asString(), GlobalSearchScope.moduleScope(module)) + ?: getPackageViaDirectoryService(sealedKtClass) ?: return emptyList() val packageScope = PackageScope(psiPackage, false, false) - moduleSourceScope.intersectWith(packageScope) + + mppAwareSearchScope.intersectWith(packageScope) } else { GlobalSearchScope.fileScope(sealedKtClass.containingFile) // Kotlin version prior to 1.5 } - val lightClass = sealedKtClass.toLightClass() ?: return emptyList() + val kotlinAsJavaSupport = KotlinAsJavaSupport.getInstance(sealedKtClass.project) + val lightClass = sealedKtClass.toLightClass() ?: kotlinAsJavaSupport.getFakeLightClass(sealedKtClass) val searchParameters = SearchParameters(lightClass, searchScope, false, true, false) return ClassInheritorsSearch.search(searchParameters) @@ -51,6 +69,10 @@ object IdeSealedClassInheritorsProvider : SealedClassInheritorsProvider() { .sortedBy(ClassDescriptor::getName) // order needs to be stable (at least for tests) } + private fun ModuleDescriptor.listCommonModulesIfAny(): Collection { + return implementedDescriptors.closure { it.implementedDescriptors } + } + private fun getPackageViaDirectoryService(ktClass: KtClass): PsiPackage? { val directory = ktClass.containingFile.containingDirectory ?: return null return JavaDirectoryService.getInstance().getPackage(directory) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt index 76054150cd0..2b53bdea18f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.util.analyzeControlFlow import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListenerCompat import org.jetbrains.kotlin.idea.caches.trackers.inBlockModificationCount -import org.jetbrains.kotlin.idea.compiler.IdeMainFunctionDetectorFactory +import org.jetbrains.kotlin.idea.compiler.IdeSealedClassInheritorsProvider import org.jetbrains.kotlin.idea.util.application.isUnitTestMode import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.TargetPlatform @@ -785,7 +785,8 @@ class ResolveElementCache( statementFilter, targetPlatform.findAnalyzerServices(file.project), file.languageVersionSettings, - IdeaModuleStructureOracle() + IdeaModuleStructureOracle(), + IdeSealedClassInheritorsProvider ).get() } diff --git a/idea/testData/multiplatform/whenExhaustivenessForSealed/common/common.kt b/idea/testData/multiplatform/whenExhaustivenessForSealed/common/common.kt new file mode 100644 index 00000000000..9914c58c433 --- /dev/null +++ b/idea/testData/multiplatform/whenExhaustivenessForSealed/common/common.kt @@ -0,0 +1,7 @@ +expect sealed class TestClass() +class CommonImplTestClass: TestClass() + + +fun checkCommon(t: TestClass): Int = when (t) { + is CommonImplTestClass -> 0 +} diff --git a/idea/testData/multiplatform/whenExhaustivenessForSealed/commonA/commonA.kt b/idea/testData/multiplatform/whenExhaustivenessForSealed/commonA/commonA.kt new file mode 100644 index 00000000000..932279efdc9 --- /dev/null +++ b/idea/testData/multiplatform/whenExhaustivenessForSealed/commonA/commonA.kt @@ -0,0 +1 @@ +class CommonAImplTestClass: TestClass() \ No newline at end of file diff --git a/idea/testData/multiplatform/whenExhaustivenessForSealed/dependencies.txt b/idea/testData/multiplatform/whenExhaustivenessForSealed/dependencies.txt new file mode 100644 index 00000000000..fead550b979 --- /dev/null +++ b/idea/testData/multiplatform/whenExhaustivenessForSealed/dependencies.txt @@ -0,0 +1,8 @@ +MODULE common { platform=[JVM, JS, Native]; additionalCompilerArgs=: -XXLanguage:+SealedInterfaces -XXLanguage:+AllowSealedInheritorsInDifferentFilesOfSamePackage } +MODULE commonA { platform=[JVM]; additionalCompilerArgs=: -XXLanguage:+SealedInterfaces -XXLanguage:+AllowSealedInheritorsInDifferentFilesOfSamePackage } +MODULE platformAX { platform=[JVM]; additionalCompilerArgs=: -XXLanguage:+SealedInterfaces -XXLanguage:+AllowSealedInheritorsInDifferentFilesOfSamePackage } +MODULE platformAY { platform=[JVM]; additionalCompilerArgs=: -XXLanguage:+SealedInterfaces -XXLanguage:+AllowSealedInheritorsInDifferentFilesOfSamePackage } + +commonA -> common { kind=DEPENDS_ON } +platformAX -> commonA { kind=DEPENDS_ON } +platformAY -> commonA { kind=DEPENDS_ON } \ No newline at end of file diff --git a/idea/testData/multiplatform/whenExhaustivenessForSealed/platformAX/platformAX.kt b/idea/testData/multiplatform/whenExhaustivenessForSealed/platformAX/platformAX.kt new file mode 100644 index 00000000000..5d8a8717ce1 --- /dev/null +++ b/idea/testData/multiplatform/whenExhaustivenessForSealed/platformAX/platformAX.kt @@ -0,0 +1,8 @@ +actual sealed class TestClass actual constructor() {} +class PlatformAXImplTestClass: TestClass() + +fun checkCommonAX(t: TestClass): Int = when (t) { + is CommonImplTestClass -> 0 + is CommonAImplTestClass -> 1 + is PlatformAXImplTestClass -> 2 +} diff --git a/idea/testData/multiplatform/whenExhaustivenessForSealed/platformAY/platformAY.kt b/idea/testData/multiplatform/whenExhaustivenessForSealed/platformAY/platformAY.kt new file mode 100644 index 00000000000..6654412c806 --- /dev/null +++ b/idea/testData/multiplatform/whenExhaustivenessForSealed/platformAY/platformAY.kt @@ -0,0 +1,8 @@ +actual sealed class TestClass actual constructor() {} +class PlatformAYImplTestClass: TestClass() + +fun checkCommonAY(t: TestClass): Int = when (t) { + is CommonImplTestClass -> 0 + is CommonAImplTestClass -> 1 + is PlatformAYImplTestClass -> 2 +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java index a0d86c053ff..dfc1a59e90e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiplatformAnalysisTestGenerated.java @@ -268,4 +268,9 @@ public class MultiplatformAnalysisTestGenerated extends AbstractMultiplatformAna public void testWeaklyIncompatibleActualInIntermediateModule() throws Exception { runTest("idea/testData/multiplatform/weaklyIncompatibleActualInIntermediateModule/"); } + + @TestMetadata("whenExhaustivenessForSealed") + public void testWhenExhaustivenessForSealed() throws Exception { + runTest("idea/testData/multiplatform/whenExhaustivenessForSealed/"); + } } From 38437fb036c71cd592a790a473178e3daffaea4a Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 11:26:19 +0300 Subject: [PATCH 043/153] [FIR] Rename `session.firSymbolProvider` to `session.symbolProvider` to avoid visual conflicts with `session.firProvider` --- .../jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt | 4 ++-- .../kotlin/fir/java/AbstractFirTypeEnhancementTest.kt | 4 ++-- .../jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt | 3 ++- .../FirMethodOfAnyImplementedInInterfaceChecker.kt | 4 ++-- .../checkers/declaration/FirSealedSupertypeChecker.kt | 8 ++++---- .../kotlin/fir/serialization/FirElementSerializer.kt | 4 ++-- .../kotlin/fir/serialization/constant/ConstantValue.kt | 4 ++-- .../kotlin/fir/backend/jvm/FirJvmBackendClassResolver.kt | 6 +++--- .../kotlin/fir/backend/jvm/FirJvmMangleComputer.kt | 4 ++-- .../jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt | 6 +++--- .../org/jetbrains/kotlin/fir/backend/Fir2IrBuiltIns.kt | 6 +++--- .../kotlin/fir/backend/Fir2IrClassifierStorage.kt | 4 ++-- .../kotlin/fir/descriptors/FirModuleDescriptor.kt | 4 ++-- .../org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt | 2 +- .../java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt | 8 ++++---- .../kotlin/fir/java/deserialization/AnnotationsLoader.kt | 6 +++--- .../deserialization/JvmBinaryAnnotationDeserializer.kt | 4 ++-- .../jetbrains/kotlin/fir/resolve/FirJavaClassMapper.kt | 2 +- .../kotlin/fir/resolve/scopes/JvmMappedScopes.kt | 4 ++-- .../kotlin/fir/FirEffectiveVisibilityResolverImpl.kt | 6 +++--- .../org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt | 4 ++-- .../src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt | 4 ++-- .../jetbrains/kotlin/fir/resolve/FirOuterClassManager.kt | 2 +- .../org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt | 4 ++-- .../jetbrains/kotlin/fir/resolve/MainSessionComponents.kt | 2 +- .../src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt | 4 ++-- .../src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt | 2 +- .../kotlin/fir/resolve/calls/tower/TowerLevels.kt | 2 +- .../providers/impl/FirDependenciesSymbolProviderImpl.kt | 4 ++-- .../resolve/providers/impl/FirQualifierResolverImpl.kt | 6 +++--- .../fir/resolve/providers/impl/FirTypeResolverImpl.kt | 2 +- .../resolve/transformers/FirImportResolveTransformer.kt | 4 ++-- .../transformers/FirSealedClassInheritorsTransformer.kt | 4 ++-- .../resolve/transformers/FirStatusResolveTransformer.kt | 5 ++--- .../resolve/transformers/body/resolve/BodyResolveUtils.kt | 4 ++-- .../body/resolve/FirAbstractBodyResolveTransformer.kt | 2 +- .../fir/scopes/impl/FirAbstractProviderBasedScope.kt | 6 +++--- .../fir/scopes/impl/FirAbstractSimpleImportingScope.kt | 4 ++-- .../kotlin/fir/scopes/impl/FirPackageMemberScope.kt | 4 ++-- .../jetbrains/kotlin/fir/types/ConeInferenceContext.kt | 6 +++--- .../jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt | 4 ++-- .../level/api/lazy/resolve/FirLazyDeclarationResolver.kt | 4 ++-- .../fir/low/level/api/sessions/FirIdeSessionFactory.kt | 8 ++++---- .../kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt | 4 ++-- .../kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt | 4 ++-- .../kotlin/idea/references/FirReferenceResolveHelper.kt | 4 ++-- .../idea/references/KtFirCollectionLiteralReference.kt | 6 +++--- 47 files changed, 101 insertions(+), 101 deletions(-) diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt index ceb5259fd88..8ee7857e8f9 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.fir import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -27,7 +27,7 @@ abstract class AbstractFirLoadBinariesTest : AbstractFirResolveWithSessionTestCa val declarationNames = DescriptorUtils.getAllDescriptors(moduleDescriptor.getPackage(packageFqName).memberScope) .mapTo(sortedSetOf()) { it.name } - val provider = session.firSymbolProvider + val provider = session.symbolProvider val builder = StringBuilder() val firRenderer = FirRenderer(builder) diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt index 26f76d172a2..cc082c6569b 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.createSession import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -140,7 +140,7 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() { val javaFirDump = StringBuilder().also { builder -> val renderer = FirRenderer(builder) - val symbolProvider = session.firSymbolProvider as FirCompositeSymbolProvider + val symbolProvider = session.symbolProvider as FirCompositeSymbolProvider val javaProvider = symbolProvider.providers.filterIsInstance().first() val topLevelJavaClasses = topPsiClasses.map { it.classId(FqName.ROOT) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 4de8ec9b974..f2989f19726 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike @@ -316,4 +317,4 @@ val FirFunctionCall.isIterator internal fun throwableClassLikeType(session: FirSession) = session.builtinTypes.throwableType.type fun ConeKotlinType.isSubtypeOfThrowable(session: FirSession) = - throwableClassLikeType(session).isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session)) \ No newline at end of file + throwableClassLikeType(session).isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session)) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMethodOfAnyImplementedInInterfaceChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMethodOfAnyImplementedInInterfaceChecker.kt index e36393679ea..295e05ad245 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMethodOfAnyImplementedInInterfaceChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMethodOfAnyImplementedInInterfaceChecker.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.utils.addToStdlib.safeAs object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker(), FirDeclarationPresenter { @@ -21,7 +21,7 @@ object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker(), F private fun getInspector(context: CheckerContext) = inspector ?: FirDeclarationInspector(this).apply { val anyClassId = context.session.builtinTypes.anyType.id - context.session.firSymbolProvider.getClassLikeSymbolByFqName(anyClassId) + context.session.symbolProvider.getClassLikeSymbolByFqName(anyClassId) ?.fir.safeAs() ?.declarations ?.filterIsInstance() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt index 91d1c9b3e64..700b30b1a5b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -47,7 +47,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { continue } - val fir = context.session.firSymbolProvider.getClassLikeSymbolByFqName(classId) + val fir = context.session.symbolProvider.getClassLikeSymbolByFqName(classId) ?.fir.safeAs() ?: continue @@ -66,7 +66,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { continue } - val fir = context.session.firSymbolProvider.getClassLikeSymbolByFqName(classId) + val fir = context.session.symbolProvider.getClassLikeSymbolByFqName(classId) ?.fir.safeAs() ?: continue @@ -85,7 +85,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { continue } - val fir = context.session.firSymbolProvider.getClassLikeSymbolByFqName(classId) + val fir = context.session.symbolProvider.getClassLikeSymbolByFqName(classId) ?.fir.safeAs() ?: continue diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt index a9e641b8747..4fbd57e802a 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.calls.varargElementType -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType import org.jetbrains.kotlin.fir.resolve.inference.suspendFunctionTypeToFunctionTypeWithContinuation @@ -891,7 +891,7 @@ class FirElementSerializer private constructor( ): FirElementSerializer { val parentClassId = klass.symbol.classId.outerClassId val parent = if (parentClassId != null && !parentClassId.isLocal) { - val parentClass = klass.session.firSymbolProvider.getClassLikeSymbolByFqName(parentClassId)!!.fir as FirRegularClass + val parentClass = klass.session.symbolProvider.getClassLikeSymbolByFqName(parentClassId)!!.fir as FirRegularClass parentSerializer ?: create(parentClass, extension, null, typeApproximator) } else { createTopLevel(klass.session, extension, typeApproximator) diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/constant/ConstantValue.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/constant/ConstantValue.kt index fce1b1b9886..a95c28f3c07 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/constant/ConstantValue.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/constant/ConstantValue.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.resolve.defaultType -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -138,7 +138,7 @@ internal class KClassValue(value: Value) : ConstantValue(valu is Value.LocalClass -> return value.type is Value.NormalClass -> { val (classId, arrayDimensions) = value.value - val klass = session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass ?: return null + val klass = session.symbolProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass ?: return null var type: ConeKotlinType = klass.defaultType().replaceArgumentsWithStarProjections() repeat(arrayDimensions) { type = type.createArrayType() diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendClassResolver.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendClassResolver.kt index 09b17e8e2b8..6a2dcc9d4a6 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendClassResolver.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendClassResolver.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.codegen.JvmBackendClassResolver import org.jetbrains.kotlin.codegen.classId import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.fir.backend.Fir2IrComponents -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.org.objectweb.asm.Type @@ -19,9 +19,9 @@ class FirJvmBackendClassResolver(val components: Fir2IrComponents) : JvmBackendC override fun resolveToClassDescriptors(type: Type): List { if (type.sort != Type.OBJECT) return emptyList() - val symbol = components.session.firSymbolProvider.getClassLikeSymbolByFqName(type.classId) ?: return emptyList() + val symbol = components.session.symbolProvider.getClassLikeSymbolByFqName(type.classId) ?: return emptyList() require(symbol is FirClassSymbol<*>) return listOf(components.classifierStorage.getIrClassSymbol(symbol).descriptor) } -} \ No newline at end of file +} diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt index 32f7ebd5eb6..272be1cc857 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode import org.jetbrains.kotlin.backend.common.serialization.mangle.collectForMangler import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol @@ -79,7 +79,7 @@ open class FirJvmMangleComputer( else -> return } if (parentClassId != null && !parentClassId.isLocal) { - val parentClassLike = this@FirJvmMangleComputer.session.firSymbolProvider.getClassLikeSymbolByFqName(parentClassId)?.fir + val parentClassLike = this@FirJvmMangleComputer.session.symbolProvider.getClassLikeSymbolByFqName(parentClassId)?.fir ?: error("Attempt to find parent ($parentClassId) for probably-local declaration!") if (parentClassLike is FirRegularClass || parentClassLike is FirTypeAlias) { parentClassLike.accept(this@FirJvmMangleComputer, false) diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt index ab8b39b178f..4650709cff2 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.defaultType -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.* import org.jetbrains.kotlin.fir.resolve.toSymbol @@ -101,7 +101,7 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext().symbol) -} \ No newline at end of file +} diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt index 3b8ba3a879a..6fd9b8b5781 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass import org.jetbrains.kotlin.fir.resolve.firProvider -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.* import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl @@ -435,7 +435,7 @@ class Fir2IrClassifierStorage( firClass as FirRegularClass val classId = firClassSymbol.classId val parentId = classId.outerClassId - val parentClass = parentId?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it) } + val parentClass = parentId?.let { session.symbolProvider.getClassLikeSymbolByFqName(it) } val irParent = declarationStorage.findIrParent(classId.packageFqName, parentClass?.toLookupTag(), firClassSymbol)!! val symbol = Fir2IrClassSymbol(signature) val irClass = firClass.convertWithOffsets { startOffset, endOffset -> diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/descriptors/FirModuleDescriptor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/descriptors/FirModuleDescriptor.kt index d6a4f8ce3b1..e33a4c70893 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/descriptors/FirModuleDescriptor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/descriptors/FirModuleDescriptor.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.TargetPlatform @@ -27,7 +27,7 @@ class FirModuleDescriptor(val session: FirSession) : ModuleDescriptor { get() = null override fun getPackage(fqName: FqName): PackageViewDescriptor { - val symbolProvider = session.firSymbolProvider + val symbolProvider = session.symbolProvider if (symbolProvider.getPackage(fqName) != null) { return FirPackageViewDescriptor(fqName, this) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt index 671723f4fe6..ecec05abe0f 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaScopeProvider.kt @@ -208,7 +208,7 @@ class JavaScopeProvider( return lazyNestedClassifierScope( klass.classId, (klass as FirJavaClass).existingNestedClassifierNames, - useSiteSession.firSymbolProvider + useSiteSession.symbolProvider ) } } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt index 79f82b3c134..19b2634eb67 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolv import org.jetbrains.kotlin.fir.resolve.bindSymbolToLookupTag import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedReferenceError -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.expectedConeType @@ -385,7 +385,7 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound( ) } - val classSymbol = session.firSymbolProvider.getClassLikeSymbolByFqName(classId) as? FirRegularClassSymbol + val classSymbol = session.symbolProvider.getClassLikeSymbolByFqName(classId) as? FirRegularClassSymbol val mappedTypeArguments = if (isRaw) { val defaultArgs = (1..classifier.typeParameters.size).map { ConeStarProjection } @@ -436,7 +436,7 @@ private fun FirRegularClass.createRawArguments( private fun buildEnumCall(session: FirSession, classId: ClassId?, entryName: Name?) = buildFunctionCall { val calleeReference = if (classId != null && entryName != null) { - session.firSymbolProvider.getClassDeclaredPropertySymbols(classId, entryName) + session.symbolProvider.getClassDeclaredPropertySymbols(classId, entryName) .firstOrNull()?.let { propertySymbol -> buildResolvedNamedReference { name = entryName @@ -503,7 +503,7 @@ private fun buildArgumentMapping( if (annotationArguments.none { it.name != null }) { return null } - val annotationClassSymbol = session.firSymbolProvider.getClassLikeSymbolByFqName(lookupTag.classId).also { + val annotationClassSymbol = session.symbolProvider.getClassLikeSymbolByFqName(lookupTag.classId).also { lookupTag.bindSymbolToLookupTag(session, it) } ?: return null val annotationConstructor = diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt index 8df4b2e9244..cfae7fe2866 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.java.createConstantOrError import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl @@ -55,7 +55,7 @@ internal class AnnotationsLoader(private val session: FirSession) { private fun ClassId.toEnumEntryReferenceExpression(name: Name): FirExpression { return buildFunctionCall { val entryPropertySymbol = - session.firSymbolProvider.getClassDeclaredPropertySymbols( + session.symbolProvider.getClassDeclaredPropertySymbols( this@toEnumEntryReferenceExpression, name, ).firstOrNull() @@ -162,4 +162,4 @@ internal class AnnotationsLoader(private val session: FirSession) { buildResolvedTypeRef { type = constructClassType(emptyArray(), isNullable = false) } -} \ No newline at end of file +} diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt index 1f420bc49cd..f5be29cdc0a 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass @@ -317,4 +317,4 @@ private fun FirSession.loadMemberAnnotations(kotlinBinaryClass: KotlinJvmBinaryC }, byteContent) return MemberAnnotations(memberAnnotations) -} \ No newline at end of file +} diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/FirJavaClassMapper.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/FirJavaClassMapper.kt index da107a5fdcf..44b5cffa088 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/FirJavaClassMapper.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/FirJavaClassMapper.kt @@ -15,6 +15,6 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass class FirJavaClassMapper(private val session: FirSession) : FirPlatformClassMapper() { override fun getCorrespondingPlatformClass(declaration: FirClassLikeDeclaration<*>): FirRegularClass? { val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(declaration.symbol.classId.asSingleFqName().toUnsafe()) - return javaClassId?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it)?.fir } as? FirRegularClass + return javaClassId?.let { session.symbolProvider.getClassLikeSymbolByFqName(it)?.fir } as? FirRegularClass } } diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt index e9d75ab0c29..5c22fe3a15f 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.classId import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.constructType -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.wrapSubstitutionScopeIfNeed import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.jvm.JvmMappedScope @@ -31,7 +31,7 @@ fun wrapScopeWithJvmMapped( val kotlinUnsafeFqName = classId.asSingleFqName().toUnsafe() val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(kotlinUnsafeFqName) ?: return declaredMemberScope - val symbolProvider = useSiteSession.firSymbolProvider + val symbolProvider = useSiteSession.symbolProvider val javaClass = symbolProvider.getClassLikeSymbolByFqName(javaClassId)?.fir as? FirRegularClass ?: return declaredMemberScope val preparedSignatures = JvmMappedScope.prepareSignatures(javaClass, JavaToKotlinClassMap.isMutable(kotlinUnsafeFqName)) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt index e9a30612e26..8c4d7230bc3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirEffectiveVisibilityResolverImpl.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -103,8 +103,8 @@ open class FirEffectiveVisibilityResolverImpl(private val session: FirSession) : if (!succeededToGetSymbol) { if (parentClassId?.isLocal == false) { // ?: is needed to get enum from enum entry - parentSymbol = session.firSymbolProvider.getClassLikeSymbolByFqName(parentClassId) - ?: parentClassId.outerClassId?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it) } + parentSymbol = session.symbolProvider.getClassLikeSymbolByFqName(parentClassId) + ?: parentClassId.outerClassId?.let { session.symbolProvider.getClassLikeSymbolByFqName(it) } parentSymbol?.fir.safeAs()?.let { parentEffectiveVisibility = resolveFor(it, null, scopeSession) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt index b4777c7ccbc..ee99dc3c589 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.PackageOrClass import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.resolveToPackageOrClass @@ -64,7 +64,7 @@ class FirQualifiedNameResolver(private val components: BodyResolveComponents) { if (qualifierStack.isEmpty()) { return null } - val symbolProvider = session.firSymbolProvider + val symbolProvider = session.symbolProvider var qualifierParts = qualifierStack.asReversed().map { it.name.asString() } var resolved: PackageOrClass? do { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt index 719f95c1c95..abc7816f2d9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.ReceiverValue import org.jetbrains.kotlin.fir.resolve.firProvider -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol @@ -133,7 +133,7 @@ abstract class FirVisibilityChecker : FirSessionComponent { private fun ClassId.ownerIfCompanion(session: FirSession): ClassId? { if (outerClassId == null || isLocal) return null - val ownerSymbol = session.firSymbolProvider.getClassLikeSymbolByFqName(this) as? FirRegularClassSymbol + val ownerSymbol = session.symbolProvider.getClassLikeSymbolByFqName(this) as? FirRegularClassSymbol return outerClassId.takeIf { ownerSymbol?.fir?.isCompanion == true } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirOuterClassManager.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirOuterClassManager.kt index 3c0646521b9..e7eff05da5e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirOuterClassManager.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirOuterClassManager.kt @@ -17,7 +17,7 @@ class FirOuterClassManager( private val session: FirSession, private val outerLocalClassForNested: Map, FirClassLikeSymbol<*>>, ) { - private val symbolProvider = session.firSymbolProvider + private val symbolProvider = session.symbolProvider fun outerClass(classSymbol: FirClassLikeSymbol<*>): FirClassLikeSymbol<*>? { if (classSymbol !is FirClassSymbol<*>) return null diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt index f127007a411..d24c64d1e60 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt @@ -25,7 +25,7 @@ fun ConeClassLikeLookupTag.toSymbol(useSiteSession: FirSession): FirClassLikeSym if (this is ConeClassLookupTagWithFixedSymbol) { return this.symbol } - val firSymbolProvider = useSiteSession.firSymbolProvider + val firSymbolProvider = useSiteSession.symbolProvider (this as? ConeClassLikeLookupTagImpl)?.boundSymbol?.takeIf { it.key === useSiteSession }?.let { return it.value } return firSymbolProvider.getClassLikeSymbolByFqName(classId).also { @@ -40,7 +40,7 @@ fun ConeClassLikeLookupTag.toSymbolOrError(useSiteSession: FirSession): FirClass fun ConeClassLikeLookupTag.toFirRegularClass(session: FirSession): FirRegularClass? = - session.firSymbolProvider.getSymbolByLookupTag(this)?.fir as? FirRegularClass + session.symbolProvider.getSymbolByLookupTag(this)?.fir as? FirRegularClass @OptIn(LookupTagInternals::class) fun ConeClassLikeLookupTagImpl.bindSymbolToLookupTag(session: FirSession, symbol: FirClassLikeSymbol<*>?) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/MainSessionComponents.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/MainSessionComponents.kt index 04f2ea1f08c..5c051b81ff2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/MainSessionComponents.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/MainSessionComponents.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache -val FirSession.firSymbolProvider: FirSymbolProvider by FirSession.sessionComponentAccessor() +val FirSession.symbolProvider: FirSymbolProvider by FirSession.sessionComponentAccessor() val FirSession.firProvider: FirProvider by FirSession.sessionComponentAccessor() val FirSession.correspondingSupertypesCache: FirCorrespondingSupertypesCache by FirSession.sessionComponentAccessor() val FirSession.declaredMemberScopeProvider: FirDeclaredMemberScopeProvider by FirSession.sessionComponentAccessor() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index eb7923544b8..9aeaaf3d4db 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -283,7 +283,7 @@ fun CallableId.isIterator(): Boolean = callableName.asString() == "iterator" && packageName.asString() in arrayOf("kotlin.collections", "kotlin.ranges") fun FirAnnotationCall.fqName(session: FirSession): FqName? { - val symbol = session.firSymbolProvider.getSymbolByTypeRef(annotationTypeRef) ?: return null + val symbol = session.symbolProvider.getSymbolByTypeRef(annotationTypeRef) ?: return null return symbol.classId.asSingleFqName() } @@ -327,7 +327,7 @@ fun FirAnnotationCall.getCorrespondingClassSymbolOrNull(session: FirSession): Fi // TODO: How to retrieve local annotaiton's constructor? null } else { - (session.firSymbolProvider.getClassLikeSymbolByFqName(it) as? FirRegularClassSymbol) + (session.symbolProvider.getClassLikeSymbolByFqName(it) as? FirRegularClassSymbol) } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt index d53b24c2d44..4ae71033773 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt @@ -241,7 +241,7 @@ private fun FirRegularClass.computeSamCandidateNames(session: FirSession): Set() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt index 73e60d9c20b..856ff5f835f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt @@ -197,7 +197,7 @@ class ScopeTowerLevel( private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>): ReceiverValue? { candidate.fir.importedFromObjectData?.let { data -> val objectClassId = data.objectClassId - val symbol = session.firSymbolProvider.getClassLikeSymbolByFqName(objectClassId) + val symbol = session.symbolProvider.getClassLikeSymbolByFqName(objectClassId) if (symbol is FirRegularClassSymbol) { val resolvedQualifier = buildResolvedQualifier { packageFqName = objectClassId.packageFqName diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirDependenciesSymbolProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirDependenciesSymbolProviderImpl.kt index 833837538fb..e8a75128e7b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirDependenciesSymbolProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirDependenciesSymbolProviderImpl.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.ThreadSafeMutableState import org.jetbrains.kotlin.fir.caches.* import org.jetbrains.kotlin.fir.dependenciesWithoutSelf -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals import org.jetbrains.kotlin.fir.symbols.CallableId @@ -34,7 +34,7 @@ open class FirDependenciesSymbolProviderImpl(session: FirSession) : FirSymbolPro protected open val dependencyProviders by lazy { val moduleInfo = session.moduleInfo ?: return@lazy emptyList() moduleInfo.dependenciesWithoutSelf().mapNotNull { - session.sessionProvider?.getSession(it)?.firSymbolProvider + session.sessionProvider?.getSession(it)?.symbolProvider }.toList() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirQualifierResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirQualifierResolverImpl.kt index 4c2fb7a4e2f..747080b6ad7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirQualifierResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirQualifierResolverImpl.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.providers.impl import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.NoMutableState import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol import org.jetbrains.kotlin.fir.types.FirQualifierPart import org.jetbrains.kotlin.name.ClassId @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.name.FqName class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver() { override fun resolveSymbolWithPrefix(parts: List, prefix: ClassId): FirClassifierSymbol<*>? { - val symbolProvider = session.firSymbolProvider + val symbolProvider = session.symbolProvider val fqName = ClassId( prefix.packageFqName, @@ -29,7 +29,7 @@ class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver() } override fun resolveSymbol(parts: List): FirClassifierSymbol<*>? { - val firProvider = session.firSymbolProvider + val firProvider = session.symbolProvider if (parts.isNotEmpty()) { val lastPart = mutableListOf() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt index 232e6ec133c..3f87e66f80b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.name.ClassId class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { private val symbolProvider by lazy { - session.firSymbolProvider + session.symbolProvider } private data class ClassIdInSession(val session: FirSession, val id: ClassId) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirImportResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirImportResolveTransformer.kt index 35793c30fad..cc0e15fd84a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirImportResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirImportResolveTransformer.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.compose @@ -34,7 +34,7 @@ open class FirImportResolveTransformer protected constructor( constructor(session: FirSession) : this(session, FirResolvePhase.IMPORTS) - private val symbolProvider: FirSymbolProvider = session.firSymbolProvider + private val symbolProvider: FirSymbolProvider = session.symbolProvider override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { checkSessionConsistency(file) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt index c5296dd5079..579c848f9cc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol @@ -77,7 +77,7 @@ class FirSealedClassInheritorsTransformer : FirTransformer() { data.computeIfAbsent(regularClass) { mutableListOf() } } - val symbolProvider = regularClass.session.firSymbolProvider + val symbolProvider = regularClass.session.symbolProvider for (typeRef in regularClass.superTypeRefs) { val parent = extractClassFromTypeRef(symbolProvider, typeRef).takeIf { it?.modality == Modality.SEALED } ?: continue diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt index 08ba47d5a25..462d29f5f04 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt @@ -11,9 +11,8 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.dfa.symbol import org.jetbrains.kotlin.fir.resolve.firProvider -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.LocalClassesNavigationInfo import org.jetbrains.kotlin.fir.scopes.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.FirScope @@ -224,7 +223,7 @@ abstract class AbstractFirStatusResolveTransformer( protected val containingClass: FirClass<*>? get() = classes.lastOrNull() private val firProvider = session.firProvider - private val symbolProvider = session.firSymbolProvider + private val symbolProvider = session.symbolProvider protected abstract fun FirDeclaration.needResolveMembers(): Boolean protected abstract fun FirDeclaration.needResolveNestedClassifiers(): Boolean diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt index b2d3da6bd55..ece2ccc7434 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression import org.jetbrains.kotlin.fir.expressions.builder.buildVarargArgumentsExpression -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.types.* @@ -108,7 +108,7 @@ fun FirBlock.writeResultType(session: FirSession) { fun ConstantValueKind<*>.expectedConeType(session: FirSession): ConeKotlinType { fun constructLiteralType(classId: ClassId, isNullable: Boolean = false): ConeKotlinType { - val symbol = session.firSymbolProvider.getClassLikeSymbolByFqName(classId) + val symbol = session.symbolProvider.getClassLikeSymbolByFqName(classId) ?: return ConeClassErrorType(ConeSimpleDiagnostic("Missing stdlib class: $classId", DiagnosticKind.MissingStdlibClass)) return symbol.toLookupTag().constructClassType(emptyArray(), isNullable) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt index a6e34ba1512..401ae73af04 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformer.kt @@ -127,7 +127,7 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb override val container: FirDeclaration get() = context.containerIfAny!! override val noExpectedType: FirTypeRef = buildImplicitTypeRef() - override val symbolProvider: FirSymbolProvider = session.firSymbolProvider + override val symbolProvider: FirSymbolProvider = session.symbolProvider override val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractProviderBasedScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractProviderBasedScope.kt index 34c235f892e..fb4bcc1667b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractProviderBasedScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractProviderBasedScope.kt @@ -6,17 +6,17 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirDependenciesSymbolProviderImpl import org.jetbrains.kotlin.fir.scopes.FirScope abstract class FirAbstractProviderBasedScope(val session: FirSession, lookupInFir: Boolean = true) : FirScope() { - val provider = when (val symbolProvider = session.firSymbolProvider) { + val provider = when (val symbolProvider = session.symbolProvider) { is FirCompositeSymbolProvider -> symbolProvider.takeIf { !lookupInFir }?.providers?.find { it is FirDependenciesSymbolProviderImpl } ?: symbolProvider else -> symbolProvider } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractSimpleImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractSimpleImportingScope.kt index 71dcf49a767..9091f302220 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractSimpleImportingScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractSimpleImportingScope.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirResolvedImport import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol @@ -27,7 +27,7 @@ abstract class FirAbstractSimpleImportingScope( override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { val imports = simpleImports[name] ?: return if (imports.isEmpty()) return - val provider = session.firSymbolProvider + val provider = session.symbolProvider for (import in imports) { val importedName = import.importedName ?: continue val classId = diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirPackageMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirPackageMemberScope.kt index 6b895a5e9df..b2c72878612 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirPackageMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirPackageMemberScope.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedForCalls import org.jetbrains.kotlin.fir.scopes.FirScope @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name class FirPackageMemberScope(val fqName: FqName, val session: FirSession) : FirScope() { - private val symbolProvider = session.firSymbolProvider + private val symbolProvider = session.symbolProvider private val classifierCache: MutableMap?> = mutableMapOf() private val functionCache: MutableMap> = mutableMapOf() private val propertyCache: MutableMap> = mutableMapOf() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt index eafd1ba2afb..18d9d81ec8b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeContext { - val symbolProvider: FirSymbolProvider get() = session.firSymbolProvider + val symbolProvider: FirSymbolProvider get() = session.symbolProvider override fun nullableNothingType(): SimpleTypeMarker { return session.builtinTypes.nullableNothingType.type//StandardClassIds.Nothing(symbolProvider).constructType(emptyArray(), true) @@ -472,7 +472,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo val classId = if (isSuspend) StandardNames.getSuspendFunctionClassId(parametersNumber) else StandardNames.getFunctionClassId(parametersNumber) - return session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.toLookupTag() + return session.symbolProvider.getClassLikeSymbolByFqName(classId)?.toLookupTag() ?: error("Can't find Function type") } @@ -480,7 +480,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo val classId = if (isSuspend) StandardNames.getKSuspendFunctionClassId(parametersNumber) else StandardNames.getKFunctionClassId(parametersNumber) - return session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.toLookupTag() + return session.symbolProvider.getClassLikeSymbolByFqName(classId)?.toLookupTag() ?: error("Can't find KFunction type") } } diff --git a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt index fd066bea142..afbeefee386 100644 --- a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt +++ b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.directExpansionType -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol @@ -278,7 +278,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() { inner class FirRenderer : FirVisitor() { private val session = firFile.session private val filePackage = firFile.packageFqName.toString().replace(".", "/") - private val symbolProvider = firFile.session.firSymbolProvider + private val symbolProvider = firFile.session.symbolProvider private fun removeCurrentFilePackage(fqName: String): String { return if (fqName.startsWith(filePackage) && !fqName.substring(filePackage.length + 1).contains("/")) { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt index 09e310ab9ac..8594aafb8ac 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector import org.jetbrains.kotlin.idea.fir.low.level.api.trasformers.FirDesignatedBodyResolveTransformerForIDE @@ -49,7 +49,7 @@ internal class FirLazyDeclarationResolver( else -> error("Invalid source of property accessor ${ktDeclaration::class}") } val containingProperty = ktContainingResolvableDeclaration - .findSourceNonLocalFirDeclaration(firFileBuilder, declaration.session.firSymbolProvider, moduleFileCache) + .findSourceNonLocalFirDeclaration(firFileBuilder, declaration.session.symbolProvider, moduleFileCache) return lazyResolveDeclaration(containingProperty, moduleFileCache, toPhase, towerDataContextCollector) } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt index c4dcfb42c2f..c8bfe92e09e 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers import org.jetbrains.kotlin.fir.dependenciesWithoutSelf import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSymbolProvider @@ -108,7 +108,7 @@ internal object FirIdeSessionFactory { builtinsAndCloneableSession, builtinTypes, librariesCache - ).firSymbolProvider + ).symbolProvider ) dependentModules .mapTo(this) { @@ -122,7 +122,7 @@ internal object FirIdeSessionFactory { sessionsCache, isRootModule = false, librariesCache, - ).firSymbolProvider + ).symbolProvider } } ) @@ -185,7 +185,7 @@ internal object FirIdeSessionFactory { ) ) add(javaSymbolProvider) - addAll((builtinsAndCloneableSession.firSymbolProvider as FirCompositeSymbolProvider).providers) + addAll((builtinsAndCloneableSession.symbolProvider as FirCompositeSymbolProvider).providers) } ) ) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt index 433f24a20a8..f94b9c3b73c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir import com.intellij.openapi.project.Project import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForCompletion import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile @@ -45,7 +45,7 @@ private constructor( override val callResolver: KtCallResolver = KtFirCallResolver(this, token) override val scopeProvider by threadLocal { KtFirScopeProvider(this, firSymbolBuilder, project, firResolveState, token) } override val symbolProvider: KtSymbolProvider = - KtFirSymbolProvider(this, firResolveState.rootModuleSession.firSymbolProvider, firResolveState, firSymbolBuilder, token) + KtFirSymbolProvider(this, firResolveState.rootModuleSession.symbolProvider, firResolveState, firSymbolBuilder, token) override val completionCandidateChecker: KtCompletionCandidateChecker = KtFirCompletionCandidateChecker(this, token) override val symbolDeclarationOverridesProvider: KtSymbolDeclarationOverridesProvider = KtFirSymbolDeclarationOverridesProvider(this, token) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt index ce51b91852c..1fab2ac2dc5 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt @@ -11,7 +11,7 @@ import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag @@ -46,7 +46,7 @@ internal class KtSymbolByFirBuilder private constructor( ) : ValidityTokenOwner { private val resolveState by weakRef(resolveState) - private val firProvider get() = resolveState.rootModuleSession.firSymbolProvider + private val firProvider get() = resolveState.rootModuleSession.symbolProvider constructor( resolveState: FirModuleResolveState, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt index 9c207087f4f..a9c65c0b055 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOperatorAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeWrongNumberOfTypeArgumentsError -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl @@ -311,7 +311,7 @@ internal object FirReferenceResolveHelper { return listOfNotNull(classId.toTargetPsi(session, symbolBuilder)) } val name = fir.importedName ?: return emptyList() - val symbolProvider = session.firSymbolProvider + val symbolProvider = session.symbolProvider @OptIn(ExperimentalStdlibApi::class) return buildList { diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirCollectionLiteralReference.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirCollectionLiteralReference.kt index 1fdabf77e94..832511215ef 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirCollectionLiteralReference.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirCollectionLiteralReference.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.idea.references import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol @@ -36,7 +36,7 @@ class KtFirCollectionLiteralReference( } private fun KtFirAnalysisSession.arrayOfSymbol(identifier: Name): KtSymbol? { - val fir = firResolveState.rootModuleSession.firSymbolProvider.getTopLevelCallableSymbols(kotlinPackage, identifier).firstOrNull { + val fir = firResolveState.rootModuleSession.symbolProvider.getTopLevelCallableSymbols(kotlinPackage, identifier).firstOrNull { /* choose (for byte array) * public fun byteArrayOf(vararg elements: kotlin.Byte): kotlin.ByteArray */ @@ -56,4 +56,4 @@ class KtFirCollectionLiteralReference( Name.identifier("${shortClassName.identifier.decapitalize()}Of") } -} \ No newline at end of file +} From c8f9cc33ef425fd4a1183b67ce1c3b4c5a77d7e1 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 11:38:12 +0300 Subject: [PATCH 044/153] [FIR] Pass all FirFiles to FirGlobalResolveProcessor.process --- .../kotlin/fir/resolve/transformers/FirResolveProcessor.kt | 4 ++-- .../fir/resolve/transformers/FirTotalResolveProcessor.kt | 2 +- .../plugin/FirGlobalClassGenerationProcessor.kt | 2 +- .../plugin/FirGlobalExtensionStatusProcessor.kt | 2 +- .../plugin/FirGlobalNewMemberGenerationProcessor.kt | 4 ++-- .../tests/org/jetbrains/kotlin/fir/FirResolveBench.kt | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirResolveProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirResolveProcessor.kt index 8778c428a0c..b24c5a4e1ed 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirResolveProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirResolveProcessor.kt @@ -16,7 +16,7 @@ annotation class AdapterForResolveProcessor sealed class FirResolveProcessor(val session: FirSession, val scopeSession: ScopeSession) abstract class FirGlobalResolveProcessor(session: FirSession, scopeSession: ScopeSession) : FirResolveProcessor(session, scopeSession) { - abstract fun process() + abstract fun process(files: Collection) } abstract class FirTransformerBasedResolveProcessor( @@ -28,4 +28,4 @@ abstract class FirTransformerBasedResolveProcessor( fun processFile(file: FirFile) { file.transform(transformer, null) } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt index 17ec0cd3524..a385324ff3b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt @@ -24,7 +24,7 @@ class FirTotalResolveProcessor(session: FirSession) { } } is FirGlobalResolveProcessor -> { - processor.process() + processor.process(files) } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalClassGenerationProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalClassGenerationProcessor.kt index 0d68e6e606b..0c17a548ff3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalClassGenerationProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalClassGenerationProcessor.kt @@ -20,7 +20,7 @@ class FirGlobalClassGenerationProcessor( session: FirSession, scopeSession: ScopeSession ) : FirGlobalResolveProcessor(session, scopeSession) { - override fun process() { + override fun process(files: Collection) { val extensions = session.extensionService.declarationGenerators if (extensions.isEmpty()) return val provider = session.predicateBasedProvider diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalExtensionStatusProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalExtensionStatusProcessor.kt index 45fb485117e..9305d649427 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalExtensionStatusProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalExtensionStatusProcessor.kt @@ -24,7 +24,7 @@ class FirGlobalExtensionStatusProcessor( session: FirSession, scopeSession: ScopeSession ) : FirGlobalResolveProcessor(session, scopeSession) { - override fun process() { + override fun process(files: Collection) { val extensions = session.extensionService.statusTransformerExtensions if (extensions.isEmpty()) return val provider = session.predicateBasedProvider diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt index 964d51b927e..24614ebd0b1 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt @@ -26,7 +26,7 @@ class FirGlobalNewMemberGenerationProcessor( private val index = session.generatedClassIndex private val provider = session.predicateBasedProvider - override fun process() { + override fun process(files: Collection) { val extensions = session.extensionService.declarationGenerators if (extensions.isEmpty()) return for (extension in extensions) { @@ -64,4 +64,4 @@ class FirGlobalNewMemberGenerationProcessor( } } } -} \ No newline at end of file +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt index 790eb388187..8aa8f282457 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt @@ -159,7 +159,7 @@ class FirResolveBench(val withProgress: Boolean) { private fun runStage(processor: FirResolveProcessor, firFileSequence: Sequence) { when (processor) { is FirTransformerBasedResolveProcessor -> runStage(processor, firFileSequence) - is FirGlobalResolveProcessor -> runStage(processor) + is FirGlobalResolveProcessor -> runStage(processor, firFileSequence.toList()) } } @@ -182,10 +182,10 @@ class FirResolveBench(val withProgress: Boolean) { } } - private fun runStage(processor: FirGlobalResolveProcessor) { + private fun runStage(processor: FirGlobalResolveProcessor, firFiles: List) { processWithTimeMeasure( processor::class, - { processor.process() } + { processor.process(firFiles) } ) { e -> val message = "Fail on stage ${processor::class}" println(message) From 490ef210ac04ede70a68af8a55625c06599dc848 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 12:17:37 +0300 Subject: [PATCH 045/153] [FIR] Support sealed class inheritors in multiple files --- .../resolve/diagnostics/sealedSupertype.kt | 2 +- .../declaration/FirSealedSupertypeChecker.kt | 43 ++----- .../kotlin/fir/FirVisibilityChecker.kt | 27 +++-- ...rLegacySealedClassInheritorsTransformer.kt | 38 ++++++ ...t => FirSealedClassInheritorsProcessor.kt} | 109 +++++++++--------- .../resolve/transformers/ResolvePhaseUtils.kt | 4 +- .../box/sealed/multipleFiles_enabled.kt | 1 - .../tests/sealed/DerivedTopLevel.fir.kt | 2 +- .../tests/sealed/ExhaustiveWithFreedom.fir.kt | 6 +- .../tests/sealed/MultipleFiles_enabled.fir.kt | 12 +- .../NestedSealedWithoutRestrictions.fir.kt | 39 ------- .../sealed/NestedSealedWithoutRestrictions.kt | 1 + .../sealed/NeverDerivedFromNested.fir.kt | 2 +- 13 files changed, 130 insertions(+), 156 deletions(-) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirLegacySealedClassInheritorsTransformer.kt rename compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/{FirSealedClassInheritorsTransformer.kt => FirSealedClassInheritorsProcessor.kt} (75%) delete mode 100644 compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/sealedSupertype.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/sealedSupertype.kt index 6bd11376197..61185630aaa 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/sealedSupertype.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/sealedSupertype.kt @@ -29,7 +29,7 @@ sealed class P { class K : P() object B { - class I : P() + class I : P() } fun test() { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt index 700b30b1a5b..35f1d502457 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedSupertypeChecker.kt @@ -20,26 +20,18 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration is FirClass<*>) { // only the file declaration is present - when { - context.containingDeclarations.size == 1 -> { - checkTopLevelDeclaration(declaration, context, reporter) - } - declaration.classId.isLocal -> { - checkLocalDeclaration(declaration, context, reporter) - } - else -> { - checkInnerDeclaration(declaration, context, reporter) - } + if (declaration.classId.isLocal) { + checkLocalDeclaration(declaration, context, reporter) + } else { + checkGlobalDeclaration(declaration, context, reporter) } } else if (declaration is FirProperty) { - val initializer = declaration.initializer.safeAs>() - ?: return - + val initializer = declaration.initializer.safeAs>() ?: return checkLocalDeclaration(initializer, context, reporter) } } - private fun checkTopLevelDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) { + private fun checkGlobalDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) { for (it in declaration.superTypeRefs) { val classId = it.coneType.classId ?: continue @@ -51,9 +43,9 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { ?.fir.safeAs() ?: continue - if (fir.status.modality == Modality.SEALED && classId.outerClassId != null) { + if (fir.status.modality == Modality.SEALED && declaration.classId.packageFqName != fir.classId.packageFqName) { reporter.reportOn(it.source, FirErrors.SEALED_SUPERTYPE, context) - return + continue } } } @@ -76,23 +68,4 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() { } } } - - private fun checkInnerDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) { - for (it in declaration.superTypeRefs) { - val classId = it.coneType.classId ?: continue - - if (classId.isLocal) { - continue - } - - val fir = context.session.symbolProvider.getClassLikeSymbolByFqName(classId) - ?.fir.safeAs() - ?: continue - - if (fir.status.modality == Modality.SEALED && !context.containingDeclarations.contains(fir)) { - reporter.reportOn(it.source, FirErrors.SEALED_SUPERTYPE, context) - return - } - } - } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt index abc7816f2d9..d2531c45207 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -65,17 +65,24 @@ abstract class FirVisibilityChecker : FirSessionComponent { Visibilities.Private, Visibilities.PrivateToThis -> { val ownerId = symbol.getOwnerId() if (declaration.session == session) { - if (ownerId == null || declaration is FirConstructor && declaration.isFromSealedClass) { - val candidateFile = when (symbol) { - is FirClassLikeSymbol<*> -> provider.getFirClassifierContainerFileIfAny(symbol) - is FirCallableSymbol<*> -> provider.getFirCallableContainerFile(symbol) - else -> null + when { + ownerId == null -> { + val candidateFile = when (symbol) { + is FirClassLikeSymbol<*> -> provider.getFirClassifierContainerFileIfAny(symbol) + is FirCallableSymbol<*> -> provider.getFirCallableContainerFile(symbol) + else -> null + } + // Top-level: visible in file + candidateFile == useSiteFile + } + declaration is FirConstructor && declaration.isFromSealedClass -> { + // Sealed class constructor: visible in same package + declaration.symbol.callableId.packageName == useSiteFile.packageFqName + } + else -> { + // Member: visible inside parent class, including all its member classes + canSeePrivateMemberOf(containingDeclarations, ownerId, session) } - // Top-level: visible in file - candidateFile == useSiteFile - } else { - // Member: visible inside parent class, including all its member classes - canSeePrivateMemberOf(containingDeclarations, ownerId, session) } } else { declaration is FirSimpleFunction && declaration.isAllowedToBeAccessedFromOutside() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirLegacySealedClassInheritorsTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirLegacySealedClassInheritorsTransformer.kt new file mode 100644 index 00000000000..bc813056e6d --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirLegacySealedClassInheritorsTransformer.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.resolve.transformers + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.name.ClassId + +/* + * This processor is needed only for IDE until there won't be proper IDE implementation + * for detecting sealed inheritors in multiple files + */ +class FirLegacySealedClassInheritorsProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) { + override val transformer = FirLegacySealedClassInheritorsTransformer() +} + +class FirLegacySealedClassInheritorsTransformer : FirTransformer() { + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { + throw IllegalStateException("Should not be there") + } + + override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { + val sealedClassInheritorsMap = mutableMapOf>() + file.accept(FirSealedClassInheritorsProcessor.InheritorsCollector, sealedClassInheritorsMap) + if (sealedClassInheritorsMap.isEmpty()) return file.compose() + return file.transform(FirSealedClassInheritorsProcessor.InheritorsTransformer(sealedClassInheritorsMap), null) + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt similarity index 75% rename from compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt rename to compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt index 579c848f9cc..98d86b67a48 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -11,38 +11,69 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.symbolProvider -import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag +import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.coneType -import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult -import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor -import org.jetbrains.kotlin.fir.visitors.FirTransformer -import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.ClassId -class FirSealedClassInheritorsProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) { - override val transformer = FirSealedClassInheritorsTransformer() -} - -class FirSealedClassInheritorsTransformer : FirTransformer() { - override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { - throw IllegalStateException("Should not be there") - } - - override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { +class FirSealedClassInheritorsProcessor( + session: FirSession, + scopeSession: ScopeSession +) : FirGlobalResolveProcessor(session, scopeSession) { + override fun process(files: Collection) { val sealedClassInheritorsMap = mutableMapOf>() - file.accept(InheritorsCollector, sealedClassInheritorsMap) - if (sealedClassInheritorsMap.isEmpty()) return file.compose() - return file.transform(InheritorsTransformer(sealedClassInheritorsMap), null) + files.forEach { it.accept(InheritorsCollector, sealedClassInheritorsMap) } + files.forEach { it.transformSingle(InheritorsTransformer(sealedClassInheritorsMap), null) } } - private class InheritorsTransformer(private val inheritorsMap: MutableMap>) : FirTransformer() { + object InheritorsCollector : FirDefaultVisitor>>() { + override fun visitElement(element: FirElement, data: MutableMap>) {} + + override fun visitFile(file: FirFile, data: MutableMap>) { + file.declarations.forEach { it.accept(this, data) } + } + + override fun visitRegularClass(regularClass: FirRegularClass, data: MutableMap>) { + regularClass.declarations.forEach { it.accept(this, data) } + + if (regularClass.modality == Modality.SEALED) { + data.computeIfAbsent(regularClass) { mutableListOf() } + } + + val symbolProvider = regularClass.session.symbolProvider + + for (typeRef in regularClass.superTypeRefs) { + val parent = extractClassFromTypeRef(symbolProvider, typeRef).takeIf { it?.modality == Modality.SEALED } ?: continue + // Inheritors of sealed class are allowed only in same package + if (parent.classId.packageFqName != regularClass.classId.packageFqName) continue + val inheritors = data.computeIfAbsent(parent) { mutableListOf() } + inheritors += regularClass.symbol.classId + } + } + + private fun extractClassFromTypeRef(symbolProvider: FirSymbolProvider, typeRef: FirTypeRef): FirRegularClass? { + val lookupTag = (typeRef.coneType as? ConeLookupTagBasedType)?.lookupTag ?: return null + val classLikeSymbol: FirClassifierSymbol<*> = symbolProvider.getSymbolByLookupTag(lookupTag) ?: return null + return when (classLikeSymbol) { + is FirRegularClassSymbol -> classLikeSymbol.fir + is FirTypeAliasSymbol -> { + classLikeSymbol.ensureResolved(FirResolvePhase.SUPER_TYPES, symbolProvider.session) + extractClassFromTypeRef(symbolProvider, classLikeSymbol.fir.expandedTypeRef) + } + else -> null + } + } + } + + class InheritorsTransformer(private val inheritorsMap: MutableMap>) : FirTransformer() { override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { return element.compose() } @@ -63,42 +94,6 @@ class FirSealedClassInheritorsTransformer : FirTransformer() { } } - private object InheritorsCollector : FirDefaultVisitor>>() { - override fun visitElement(element: FirElement, data: MutableMap>) {} - - override fun visitFile(file: FirFile, data: MutableMap>) { - file.declarations.forEach { it.accept(this, data) } - } - - override fun visitRegularClass(regularClass: FirRegularClass, data: MutableMap>) { - regularClass.declarations.forEach { it.accept(this, data) } - - if (regularClass.modality == Modality.SEALED) { - data.computeIfAbsent(regularClass) { mutableListOf() } - } - - val symbolProvider = regularClass.session.symbolProvider - - for (typeRef in regularClass.superTypeRefs) { - val parent = extractClassFromTypeRef(symbolProvider, typeRef).takeIf { it?.modality == Modality.SEALED } ?: continue - val inheritors = data.computeIfAbsent(parent) { mutableListOf() } - inheritors += regularClass.symbol.classId - } - } - - private fun extractClassFromTypeRef(symbolProvider: FirSymbolProvider, typeRef: FirTypeRef): FirRegularClass? { - val lookupTag = (typeRef.coneType as? ConeLookupTagBasedType)?.lookupTag ?: return null - val classLikeSymbol: FirClassifierSymbol<*> = symbolProvider.getSymbolByLookupTag(lookupTag) ?: return null - return when (classLikeSymbol) { - is FirRegularClassSymbol -> classLikeSymbol.fir - is FirTypeAliasSymbol -> { - classLikeSymbol.ensureResolved(FirResolvePhase.SUPER_TYPES, symbolProvider.session) - extractClassFromTypeRef(symbolProvider, classLikeSymbol.fir.expandedTypeRef) - } - else -> null - } - } - } } object SealedClassInheritorsKey : FirDeclarationDataKey() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt index ab4467a3462..a4e76d1a194 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt @@ -50,7 +50,7 @@ fun FirResolvePhase.createTransformerBasedProcessorByPhase( CLASS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove IMPORTS -> FirImportResolveProcessor(session, scopeSession) SUPER_TYPES -> FirSupertypeResolverProcessor(session, scopeSession) - SEALED_CLASS_INHERITORS -> FirSealedClassInheritorsProcessor(session, scopeSession) + SEALED_CLASS_INHERITORS -> FirLegacySealedClassInheritorsProcessor(session, scopeSession) TYPES -> FirTypeResolveProcessor(session, scopeSession) ARGUMENTS_OF_PLUGIN_ANNOTATIONS -> FirAnnotationArgumentsResolveProcessor(session, scopeSession) EXTENSION_STATUS_UPDATE -> FirTransformerBasedExtensionStatusProcessor(session, scopeSession) @@ -74,4 +74,4 @@ private class FirDummyTransformerBasedProcessor( return element.compose() } } -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/sealed/multipleFiles_enabled.kt b/compiler/testData/codegen/box/sealed/multipleFiles_enabled.kt index ff712206259..a54e80d1569 100644 --- a/compiler/testData/codegen/box/sealed/multipleFiles_enabled.kt +++ b/compiler/testData/codegen/box/sealed/multipleFiles_enabled.kt @@ -1,5 +1,4 @@ // ISSUE: KT-13495 -// IGNORE_BACKEND_FIR: JVM_IR // !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage // FILE: Base.kt diff --git a/compiler/testData/diagnostics/tests/sealed/DerivedTopLevel.fir.kt b/compiler/testData/diagnostics/tests/sealed/DerivedTopLevel.fir.kt index 26c557d48cd..4b6d60300f8 100644 --- a/compiler/testData/diagnostics/tests/sealed/DerivedTopLevel.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/DerivedTopLevel.fir.kt @@ -1,7 +1,7 @@ sealed class Base class Derived: Base() { - class Derived2: Base() + class Derived2: Base() } fun test() { diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt index f90edc7720d..302a7bd38d8 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt @@ -10,14 +10,14 @@ sealed class Base { // FILE: B.kt -class B : Base() +class B : Base() // FILE: Container.kt class Containter { - class C : Base() + class C : Base() - inner class D : Base() + inner class D : Base() } // FILE: main.kt diff --git a/compiler/testData/diagnostics/tests/sealed/MultipleFiles_enabled.fir.kt b/compiler/testData/diagnostics/tests/sealed/MultipleFiles_enabled.fir.kt index 3300a9cb6aa..455e7591dde 100644 --- a/compiler/testData/diagnostics/tests/sealed/MultipleFiles_enabled.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/MultipleFiles_enabled.fir.kt @@ -13,21 +13,21 @@ sealed class Base { package foo -class B : Base() +class B : Base() // FILE: c.kt package foo class Container { - class C : Base() + class C : Base() - inner class D : Base() + inner class D : Base() - val anon = object : Base() {} // Should be an error + val anon = object : Base() {} // Should be an error fun someFun() { - class LocalClass : Base() {} // Should be an error + class LocalClass : Base() {} // Should be an error } } @@ -37,4 +37,4 @@ package bar import foo.Base -class E : Base() +class E : Base() diff --git a/compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.fir.kt b/compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.fir.kt deleted file mode 100644 index ff3c72191d0..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.fir.kt +++ /dev/null @@ -1,39 +0,0 @@ -// ISSUE: KT-13495 -// !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage -// !DIAGNOSTICS: -UNUSED_VARIABLE - -// FILE: base.kt - -package foo - -class Container { - sealed class Base -} - -// FILE: a.kt - -package foo - -class A : Container.Base() - -// FILE: b.kt - -package foo - -class BContainer { - class B : Container.Base() - - inner class C : Container.Base() -} - -// FILE: test.kt - -package foo - -fun test(base: Container.Base) { - val x = when (base) { - is A -> 1 - is BContainer.B -> 2 - is BContainer.C -> 3 - } -} diff --git a/compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.kt b/compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.kt index c6da20d58a6..31716bacff5 100644 --- a/compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.kt +++ b/compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // ISSUE: KT-13495 // !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage // !DIAGNOSTICS: -UNUSED_VARIABLE diff --git a/compiler/testData/diagnostics/tests/sealed/NeverDerivedFromNested.fir.kt b/compiler/testData/diagnostics/tests/sealed/NeverDerivedFromNested.fir.kt index f455a892688..b59a1dae1f6 100644 --- a/compiler/testData/diagnostics/tests/sealed/NeverDerivedFromNested.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/NeverDerivedFromNested.fir.kt @@ -2,7 +2,7 @@ class A { sealed class Base } -class Derived : A.Base() +class Derived : A.Base() fun test() { class DerivedLocal : A.Base() From 11ab37160eeb5b9f1480419072b02b47fb795174 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 12:49:24 +0300 Subject: [PATCH 046/153] [FIR] Save info that when was used as expression --- ...otTouchedTilContractsPhaseTestGenerated.java | 5 +++++ .../resolve/whenWithWhenAsStatement.fir.txt | 16 ++++++++++++++++ .../testData/resolve/whenWithWhenAsStatement.kt | 8 ++++++++ .../runners/FirDiagnosticTestGenerated.java | 6 ++++++ ...irDiagnosticsWithLightTreeTestGenerated.java | 6 ++++++ .../lightTree/converter/ExpressionsConverter.kt | 17 ++++++++++++++++- .../kotlin/fir/builder/RawFirBuilder.kt | 16 ++++++++++++++++ .../src/org/jetbrains/kotlin/fir/CopyUtils.kt | 2 ++ .../kotlin/fir/expressions/FirWhenExpression.kt | 1 + .../builder/FirWhenExpressionBuilder.kt | 4 +++- .../expressions/impl/FirWhenExpressionImpl.kt | 1 + .../fir/tree/generator/NodeConfigurator.kt | 1 + 12 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.kt diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 24546bf8cde..ee0e5335d39 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -499,6 +499,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/whenInference.kt"); } + @TestMetadata("whenWithWhenAsStatement.kt") + public void testWhenWithWhenAsStatement() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.kt"); + } + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/arguments") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.fir.txt b/compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.fir.txt new file mode 100644 index 00000000000..6c4ff584b91 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.fir.txt @@ -0,0 +1,16 @@ +FILE: whenWithWhenAsStatement.kt + public final fun test(value: R|kotlin/Int|): R|kotlin/Unit| { + when (R|/value|) { + ==($subj$, Int(0)) -> { + } + ==($subj$, Int(1)) -> { + when (R|/value|) { + ==($subj$, Int(2)) -> { + Boolean(false) + } + } + + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.kt b/compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.kt new file mode 100644 index 00000000000..2c209a60f98 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.kt @@ -0,0 +1,8 @@ +fun test(value: Int) { + when (value) { + 0 -> {} + 1 -> when (value) { + 2 -> false + } + } +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 8b9c3797d72..604282878a9 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -590,6 +590,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/whenInference.kt"); } + @Test + @TestMetadata("whenWithWhenAsStatement.kt") + public void testWhenWithWhenAsStatement() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.kt"); + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/arguments") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 04ec51b634d..2324378a3ec 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -593,6 +593,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/whenInference.kt"); } + @Test + @TestMetadata("whenWithWhenAsStatement.kt") + public void testWhenWithWhenAsStatement() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/whenWithWhenAsStatement.kt"); + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/arguments") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index d95bd4e607c..7ff09cd0452 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.lightTree.converter import com.intellij.lang.LighterASTNode import com.intellij.psi.TokenType import com.intellij.util.diff.FlyweightCapableTreeStructure +import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -664,6 +665,7 @@ class ExpressionsConverter( source = whenExpression.toFirSourceElement() this.subject = subjectExpression this.subjectVariable = subjectVariable + usedAsExpression = whenExpression.usedAsExpression for (entry in whenEntries) { val branch = entry.firBlock branches += if (!entry.isElse) { @@ -1095,11 +1097,24 @@ class ExpressionsConverter( condition = buildElseIfTrueCondition() result = elseBranch } - } + usedAsExpression = ifExpression.usedAsExpression } } + private val LighterASTNode.usedAsExpression: Boolean + get() { + val parent = getParent() ?: return true + val parentTokenType = parent.tokenType + if (parentTokenType == BLOCK) return false + if (parentTokenType == ELSE || parentTokenType == WHEN_ENTRY) { + return parent.getParent()?.usedAsExpression ?: true + } + if (parentTokenType != BODY) return true + val type = parent.getParent()?.tokenType ?: return true + return !(type == FOR || type == WHILE || type == DO_WHILE) + } + /** * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseJump * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitBreakExpression diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 214134975b2..7c960eebca1 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -1546,6 +1546,7 @@ class RawFirBuilder( result = expression.`else`.toFirBlock() } } + usedAsExpression = expression.usedAsExpression } } @@ -1583,6 +1584,7 @@ class RawFirBuilder( source = expression.toFirSourceElement() this.subject = subjectExpression this.subjectVariable = subjectVariable + usedAsExpression = expression.usedAsExpression for (entry in expression.entries) { val entrySource = entry.toFirSourceElement() @@ -1621,6 +1623,20 @@ class RawFirBuilder( } } + private val KtExpression.usedAsExpression: Boolean + get() { + if (parent is KtBlockExpression) return false + when (parent.elementType) { + KtNodeTypes.ELSE, KtNodeTypes.WHEN_ENTRY -> { + return (parent.parent as? KtExpression)?.usedAsExpression ?: true + } + } + // Here we check that when used is a single statement of a loop + if (parent !is KtContainerNodeForControlStructureBody) return true + val type = parent.parent.elementType + return !(type == KtNodeTypes.FOR || type == KtNodeTypes.WHILE || type == KtNodeTypes.DO_WHILE) + } + override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Unit): FirElement { return FirDoWhileLoopBuilder().apply { source = expression.toFirSourceElement() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt index 7221a374a20..7d43c90ee06 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt @@ -137,6 +137,8 @@ fun FirWhenExpression.copy( branches += this@copy.branches typeRef = resultType this.annotations += annotations + usedAsExpression = this@copy.usedAsExpression + isExhaustive = this@copy.isExhaustive } fun FirTryExpression.copy( diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWhenExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWhenExpression.kt index b8f1338dd76..807c8bf0aa6 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWhenExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWhenExpression.kt @@ -25,6 +25,7 @@ abstract class FirWhenExpression : FirExpression(), FirResolvable { abstract val subjectVariable: FirVariable<*>? abstract val branches: List abstract val isExhaustive: Boolean + abstract val usedAsExpression: Boolean override fun accept(visitor: FirVisitor, data: D): R = visitor.visitWhenExpression(this, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirWhenExpressionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirWhenExpressionBuilder.kt index 1c7b74c6554..c2c8f8c2a15 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirWhenExpressionBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirWhenExpressionBuilder.kt @@ -37,6 +37,7 @@ class FirWhenExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBui var subjectVariable: FirVariable<*>? = null val branches: MutableList = mutableListOf() var isExhaustive: Boolean = false + var usedAsExpression: Boolean by kotlin.properties.Delegates.notNull() override fun build(): FirWhenExpression { return FirWhenExpressionImpl( @@ -48,13 +49,14 @@ class FirWhenExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBui subjectVariable, branches, isExhaustive, + usedAsExpression, ) } } @OptIn(ExperimentalContracts::class) -inline fun buildWhenExpression(init: FirWhenExpressionBuilder.() -> Unit = {}): FirWhenExpression { +inline fun buildWhenExpression(init: FirWhenExpressionBuilder.() -> Unit): FirWhenExpression { contract { callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWhenExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWhenExpressionImpl.kt index 7b0074e048d..79eaebe408a 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWhenExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWhenExpressionImpl.kt @@ -29,6 +29,7 @@ internal class FirWhenExpressionImpl( override var subjectVariable: FirVariable<*>?, override val branches: MutableList, override var isExhaustive: Boolean, + override val usedAsExpression: Boolean, ) : FirWhenExpression() { override fun acceptChildren(visitor: FirVisitor, data: D) { typeRef.accept(visitor, data) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index ae47709304d..9be4b83fa77 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -588,6 +588,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +field("subjectVariable", variable.withArgs("F" to "*"), nullable = true) +fieldList("branches", whenBranch).withTransform() +booleanField("isExhaustive", withReplace = true) + +booleanField("usedAsExpression") needTransformOtherChildren() } From 6469900b5ee0297ddcfc8443b28ce922da3635bf Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 14:34:05 +0300 Subject: [PATCH 047/153] [FIR] Fix forgotten light source element for if expression --- .../kotlin/fir/lightTree/converter/ExpressionsConverter.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index 7ff09cd0452..c5250d5a05f 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -1084,6 +1084,7 @@ class ExpressionsConverter( } return buildWhenExpression { + source = ifExpression.toFirSourceElement() val trueBranch = convertLoopBody(thenBlock) branches += buildWhenBranch { source = thenBlock?.toFirSourceElement() From 76f9830b47cf7b7760170dffde62934813be2548 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 15:17:46 +0300 Subject: [PATCH 048/153] [FIR] Fix checking for boolean exhaustiveness with || in branch --- .../transformers/FirWhenExhaustivenessTransformer.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt index f9097aa2c3d..0cc124b1727 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt @@ -232,5 +232,11 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe } } } + + override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: BooleanExhaustivenessFlags) { + if (binaryLogicExpression.kind == LogicOperationKind.OR) { + binaryLogicExpression.acceptChildren(this, data) + } + } } } From 3f715e671da25db001a3e05f9235af54837eb265 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 15:23:45 +0300 Subject: [PATCH 049/153] [FIR] Fix checking for null exhaustiveness with expression of Nothing? type --- .../transformers/FirWhenExhaustivenessTransformer.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt index 0cc124b1727..93fe1316437 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt @@ -97,6 +97,10 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe } } is FirQualifiedAccessExpression -> { + if (argument.typeRef.isNullableNothing) { + data.containsNull = true + return + } val reference = argument.calleeReference as? FirResolvedNamedReference ?: return val symbol = (reference.resolvedSymbol.fir as? FirEnumEntry)?.symbol ?: return @@ -185,6 +189,12 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe is FirResolvedQualifier -> { argument.typeRef.accept(this, data) } + + is FirQualifiedAccessExpression -> { + if (argument.typeRef.isNullableNothing) { + data.containsNull = true + } + } } } } From 8dd9d981292ceb0f2e1cfdb65d40b59341e62bc2 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 15:41:57 +0300 Subject: [PATCH 050/153] [FIR] Implement checker for exhaustive when's in expression position --- ...TouchedTilContractsPhaseTestGenerated.java | 139 +++++++++++----- .../negative/missingBooleanBranch.fir.txt | 55 +++++++ .../negative/missingBooleanBranch.kt | 33 ++++ .../negative/missingElse.fir.txt | 41 +++++ .../exhaustiveness/negative/missingElse.kt | 23 +++ .../negative/missingEnumEntry.fir.txt | 63 ++++++++ .../negative/missingEnumEntry.kt | 33 ++++ .../negative/missingSealedInheritor.fir.txt | 84 ++++++++++ .../negative/missingSealedInheritor.kt | 50 ++++++ .../positive}/exhaustiveWhenAndDNNType.dot | 0 .../exhaustiveWhenAndDNNType.fir.txt | 0 .../positive}/exhaustiveWhenAndDNNType.kt | 0 .../exhaustiveWhenAndFlexibleType.fir.txt | 0 .../exhaustiveWhenAndFlexibleType.kt | 0 .../positive}/exhaustiveness_boolean.fir.txt | 0 .../positive}/exhaustiveness_boolean.kt | 4 +- .../positive}/exhaustiveness_enum.fir.txt | 0 .../positive}/exhaustiveness_enum.kt | 6 +- .../positive}/exhaustiveness_enumJava.fir.txt | 0 .../positive}/exhaustiveness_enumJava.kt | 6 +- .../exhaustiveness_sealedClass.fir.txt | 0 .../positive}/exhaustiveness_sealedClass.kt | 6 +- .../exhaustiveness_sealedObject.fir.txt | 0 .../positive}/exhaustiveness_sealedObject.kt | 0 .../exhaustiveness_sealedSubClass.fir.txt | 0 .../exhaustiveness_sealedSubClass.kt | 8 +- .../testData/resolve/whenElse.kt | 12 +- .../runners/FirDiagnosticTestGenerated.java | 150 +++++++++++------ ...DiagnosticsWithLightTreeTestGenerated.java | 153 ++++++++++++------ .../kotlin/fir/checkers/generator/Main.kt | 7 +- .../expression/ComposedExpressionCheckers.kt | 4 + .../checkers/expression/ExpressionCheckers.kt | 2 + .../expression/FirExpressionCheckerAliases.kt | 2 + .../expression/FirExhaustiveWhenChecker.kt | 31 ++++ .../ExpressionCheckersDiagnosticComponent.kt | 2 +- .../diagnostics/FirDefaultErrorMessages.kt | 6 + .../fir/analysis/diagnostics/FirErrors.kt | 4 + .../LightTreePositioningStrategies.kt | 28 ++++ .../SourceElementPositioningStrategies.kt | 12 +- .../fir/checkers/CommonExpressionCheckers.kt | 4 + .../converter/ExpressionsConverter.kt | 5 +- .../kotlin/fir/builder/RawFirBuilder.kt | 4 + .../diagnostics/PositioningStrategies.kt | 7 + .../tests/FunctionCalleeExpressions.fir.kt | 2 +- .../tests/FunctionReturnTypes.fir.kt | 4 +- .../controlFlowAnalysis/kt1185enums.fir.kt | 6 +- .../tests/controlStructures/emptyIf.fir.kt | 16 -- .../tests/controlStructures/emptyIf.kt | 1 + .../ifWhenToAnyComplexExpressions.fir.kt | 4 +- .../ifWhenWithoutElse.fir.kt | 58 +++---- .../improperElseInExpression.fir.kt | 4 +- .../kt770.kt351.kt735_StatementType.fir.kt | 4 +- .../controlStructures/when.kt234.kt973.fir.kt | 2 +- .../diagnostics/tests/dataFlow/EmptyIf.fir.kt | 6 +- .../diagnostics/tests/infos/SmartCasts.fir.kt | 2 +- .../tests/sealed/ExhaustiveOnRoot.fir.kt | 6 +- .../tests/sealed/ExhaustiveOnTree.fir.kt | 4 +- .../sealed/ExhaustiveOnTriangleStar.fir.kt | 24 --- .../tests/sealed/ExhaustiveOnTriangleStar.kt | 1 + .../sealed/ExhaustiveWhenMultipleInner.fir.kt | 47 ------ .../sealed/ExhaustiveWhenMultipleInner.kt | 1 + .../tests/sealed/ExhaustiveWithFreedom.fir.kt | 64 -------- .../tests/sealed/ExhaustiveWithFreedom.kt | 1 + .../tests/sealed/NonExhaustiveWhen.fir.kt | 14 -- .../tests/sealed/NonExhaustiveWhen.kt | 1 + .../sealed/NonExhaustiveWhenNegated.fir.kt | 14 -- .../tests/sealed/NonExhaustiveWhenNegated.kt | 1 + ...NonExhaustiveWhenWithAdditionalCase.fir.kt | 22 --- .../NonExhaustiveWhenWithAdditionalCase.kt | 1 + .../NonExhaustiveWhenWithAnyCase.fir.kt | 2 +- .../sealed/TreeWhenFunctionalNoIs.fir.kt | 4 +- .../tests/sealed/WhenOnEmptySealed.fir.kt | 11 -- .../tests/sealed/WhenOnEmptySealed.kt | 1 + .../kt27221_irrelevantClasses.fir.kt | 6 +- .../loops/elvisIfBreakInsideWhileTrue.fir.kt | 9 ++ .../loops/elvisIfBreakInsideWhileTrue.kt | 3 +- .../tests/unit/nullableUnit.fir.kt | 5 - .../diagnostics/tests/unit/nullableUnit.kt | 1 + .../tests/when/ElseOnNullableEnum.fir.kt | 2 +- ...fir.kt => ExhaustiveBooleanComplex.fir.kt} | 18 +-- .../tests/when/ExhaustiveBooleanComplex.kt | 1 - .../tests/when/ExhaustiveEnumIs.fir.kt | 2 +- .../tests/when/ExhaustiveEnumMixed.fir.kt | 2 +- .../tests/when/NoElseExpectedUnit.fir.kt | 16 -- .../tests/when/NoElseExpectedUnit.kt | 1 + .../tests/when/NoElseNoExpectedType.fir.kt | 15 -- .../tests/when/NoElseNoExpectedType.kt | 1 + .../tests/when/NoElseReturnedNonUnit.fir.kt | 14 -- .../tests/when/NoElseReturnedNonUnit.kt | 1 + .../tests/when/NoElseReturnedUnit.fir.kt | 16 -- .../tests/when/NoElseReturnedUnit.kt | 1 + .../when/NonExhaustiveBooleanNullable.kt | 1 + .../when/NonExhaustivePlatformEnum.fir.kt | 29 ---- .../tests/when/NonExhaustivePlatformEnum.kt | 1 + .../NonExhaustiveWithNullabilityCheck.fir.kt | 2 +- .../tests/when/TopLevelSealed.fir.kt | 32 ---- .../diagnostics/tests/when/TopLevelSealed.kt | 1 + .../diagnostics/tests/when/kt4434.fir.kt | 2 +- .../nestedWhenWithSubject.fir.kt | 2 +- .../smartcastToEnum.fir.kt | 18 --- .../withSubjectVariable/smartcastToEnum.kt | 1 + .../smartcastToSealed.fir.kt | 20 --- .../withSubjectVariable/smartcastToSealed.kt | 1 + 103 files changed, 919 insertions(+), 617 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveWhenAndDNNType.dot (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveWhenAndDNNType.fir.txt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveWhenAndDNNType.kt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveWhenAndFlexibleType.fir.txt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveWhenAndFlexibleType.kt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_boolean.fir.txt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_boolean.kt (78%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_enum.fir.txt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_enum.kt (84%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_enumJava.fir.txt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_enumJava.kt (89%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_sealedClass.fir.txt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_sealedClass.kt (86%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_sealedObject.fir.txt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_sealedObject.kt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_sealedSubClass.fir.txt (100%) rename compiler/fir/analysis-tests/testData/resolve/{ => exhaustiveness/positive}/exhaustiveness_sealedSubClass.kt (83%) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt delete mode 100644 compiler/testData/diagnostics/tests/controlStructures/emptyIf.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.fir.kt create mode 100644 compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/unit/nullableUnit.fir.kt rename compiler/testData/diagnostics/tests/when/{NonExhaustiveBooleanNullable.fir.kt => ExhaustiveBooleanComplex.fir.kt} (54%) delete mode 100644 compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/when/TopLevelSealed.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.fir.kt diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index ee0e5335d39..ae7e3528124 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -139,46 +139,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/enumWithCompanion.kt"); } - @TestMetadata("exhaustiveWhenAndDNNType.kt") - public void testExhaustiveWhenAndDNNType() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt"); - } - - @TestMetadata("exhaustiveWhenAndFlexibleType.kt") - public void testExhaustiveWhenAndFlexibleType() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt"); - } - - @TestMetadata("exhaustiveness_boolean.kt") - public void testExhaustiveness_boolean() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt"); - } - - @TestMetadata("exhaustiveness_enum.kt") - public void testExhaustiveness_enum() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt"); - } - - @TestMetadata("exhaustiveness_enumJava.kt") - public void testExhaustiveness_enumJava() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt"); - } - - @TestMetadata("exhaustiveness_sealedClass.kt") - public void testExhaustiveness_sealedClass() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt"); - } - - @TestMetadata("exhaustiveness_sealedObject.kt") - public void testExhaustiveness_sealedObject() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt"); - } - - @TestMetadata("exhaustiveness_sealedSubClass.kt") - public void testExhaustiveness_sealedSubClass() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt"); - } - @TestMetadata("extension.kt") public void testExtension() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/extension.kt"); @@ -1271,6 +1231,105 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract } } + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Exhaustiveness extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInExhaustiveness() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Negative extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInNegative() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("missingBooleanBranch.kt") + public void testMissingBooleanBranch() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt"); + } + + @TestMetadata("missingElse.kt") + public void testMissingElse() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt"); + } + + @TestMetadata("missingEnumEntry.kt") + public void testMissingEnumEntry() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt"); + } + + @TestMetadata("missingSealedInheritor.kt") + public void testMissingSealedInheritor() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt"); + } + } + + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Positive extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPositive() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("exhaustiveWhenAndDNNType.kt") + public void testExhaustiveWhenAndDNNType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt"); + } + + @TestMetadata("exhaustiveWhenAndFlexibleType.kt") + public void testExhaustiveWhenAndFlexibleType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt"); + } + + @TestMetadata("exhaustiveness_boolean.kt") + public void testExhaustiveness_boolean() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt"); + } + + @TestMetadata("exhaustiveness_enum.kt") + public void testExhaustiveness_enum() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt"); + } + + @TestMetadata("exhaustiveness_enumJava.kt") + public void testExhaustiveness_enumJava() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt"); + } + + @TestMetadata("exhaustiveness_sealedClass.kt") + public void testExhaustiveness_sealedClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt"); + } + + @TestMetadata("exhaustiveness_sealedObject.kt") + public void testExhaustiveness_sealedObject() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt"); + } + + @TestMetadata("exhaustiveness_sealedSubClass.kt") + public void testExhaustiveness_sealedSubClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt"); + } + } + } + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.fir.txt new file mode 100644 index 00000000000..8e060626a81 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.fir.txt @@ -0,0 +1,55 @@ +FILE: missingBooleanBranch.kt + public final fun test_1(cond: R|kotlin/Boolean|): R|kotlin/Unit| { + lval x: R|kotlin/Unit| = when (R|/cond|) { + ==($subj$, Boolean(true)) -> { + Int(1) + } + } + + lval y: R|kotlin/Unit| = when (R|/cond|) { + ==($subj$, Boolean(false)) -> { + Int(2) + } + } + + lval z: R|kotlin/Int| = when (R|/cond|) { + ==($subj$, Boolean(true)) -> { + Int(1) + } + ==($subj$, Boolean(false)) -> { + Int(2) + } + } + + } + public final fun test_2(cond: R|kotlin/Boolean?|): R|kotlin/Unit| { + lval x: R|kotlin/Unit| = when (R|/cond|) { + ==($subj$, Boolean(true)) -> { + Int(1) + } + ==($subj$, Boolean(false)) -> { + Int(2) + } + } + + lval x: R|kotlin/Int| = when (R|/cond|) { + ==($subj$, Boolean(true)) -> { + Int(1) + } + ==($subj$, Boolean(false)) -> { + Int(2) + } + ==($subj$, Null(null)) -> { + Int(3) + } + } + + } + public final fun test_3(cond: R|kotlin/Boolean|): R|kotlin/Unit| { + when (R|/cond|) { + ==($subj$, Boolean(true)) -> { + Int(1) + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt new file mode 100644 index 00000000000..ddf84b51870 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt @@ -0,0 +1,33 @@ +fun test_1(cond: Boolean) { + val x = when (cond) { + true -> 1 + } + + val y = when (cond) { + false -> 2 + } + + val z = when (cond) { + true -> 1 + false -> 2 + } +} + +fun test_2(cond: Boolean?) { + val x = when (cond) { + true -> 1 + false -> 2 + } + + val x = when (cond) { + true -> 1 + false -> 2 + null -> 3 + } +} + +fun test_3(cond: Boolean) { + when (cond) { + true -> 1 + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.fir.txt new file mode 100644 index 00000000000..791d4a1457f --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.fir.txt @@ -0,0 +1,41 @@ +FILE: missingElse.kt + public final fun test(a: R|kotlin/Any|): R|kotlin/Unit| { + lval x: R|kotlin/Unit| = when (R|/a|) { + ($subj$ is R|kotlin/Int|) -> { + Int(1) + } + ($subj$ is R|kotlin/String|) -> { + Int(2) + } + } + + lval y: R|kotlin/Int| = when (R|/a|) { + else -> { + Int(1) + } + } + + lval z: R|kotlin/Int| = when (R|/a|) { + ($subj$ is R|kotlin/Int|) -> { + Int(1) + } + ($subj$ is R|kotlin/String|) -> { + Int(2) + } + else -> { + Int(3) + } + } + + } + public final fun test_2(a: R|kotlin/Any|): R|kotlin/Unit| { + when (R|/a|) { + ($subj$ is R|kotlin/String|) -> { + Int(1) + } + ($subj$ is R|kotlin/Int|) -> { + Int(2) + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt new file mode 100644 index 00000000000..8b95fcac476 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt @@ -0,0 +1,23 @@ +fun test(a: Any) { + val x = when (a) { + is Int -> 1 + is String -> 2 + } + + val y = when (a) { + else -> 1 + } + + val z = when (a) { + is Int -> 1 + is String -> 2 + else -> 3 + } +} + +fun test_2(a: Any) { + when (a) { + is String -> 1 + is Int -> 2 + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.fir.txt new file mode 100644 index 00000000000..ae6201fee17 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.fir.txt @@ -0,0 +1,63 @@ +FILE: missingEnumEntry.kt + public final enum class SomeEnum : R|kotlin/Enum| { + private constructor(): R|SomeEnum| { + super|>() + } + + public final static enum entry A: R|SomeEnum| + public final static enum entry B: R|SomeEnum| + public final static fun values(): R|kotlin/Array| { + } + + public final static fun valueOf(value: R|kotlin/String|): R|SomeEnum| { + } + + } + public final fun test_1(enum: R|SomeEnum|): R|kotlin/Unit| { + lval x: R|kotlin/Unit| = when (R|/enum|) { + ==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> { + Int(1) + } + } + + lval y: R|kotlin/Int| = when (R|/enum|) { + ==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> { + Int(1) + } + ==($subj$, Q|SomeEnum|.R|/SomeEnum.B|) -> { + Int(2) + } + } + + } + public final fun test_2(enum: R|SomeEnum?|): R|kotlin/Unit| { + lval x: R|kotlin/Unit| = when (R|/enum|) { + ==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> { + Int(1) + } + ==($subj$, Q|SomeEnum|.R|/SomeEnum.B|) -> { + Int(2) + } + } + + lval y: R|kotlin/Int| = when (R|/enum|) { + ==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> { + Int(1) + } + ==($subj$, Q|SomeEnum|.R|/SomeEnum.B|) -> { + Int(2) + } + ==($subj$, Null(null)) -> { + Int(3) + } + } + + } + public final fun test_3(enum: R|SomeEnum|): R|kotlin/Unit| { + when (R|/enum|) { + ==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> { + Int(1) + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt new file mode 100644 index 00000000000..75355434441 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt @@ -0,0 +1,33 @@ +enum class SomeEnum { + A, B +} + +fun test_1(enum: SomeEnum) { + val x = when (enum) { + SomeEnum.A -> 1 + } + + val y = when (enum) { + SomeEnum.A -> 1 + SomeEnum.B -> 2 + } +} + +fun test_2(enum: SomeEnum?) { + val x = when (enum) { + SomeEnum.A -> 1 + SomeEnum.B -> 2 + } + + val y = when (enum) { + SomeEnum.A -> 1 + SomeEnum.B -> 2 + null -> 3 + } +} + +fun test_3(enum: SomeEnum) { + when (enum) { + SomeEnum.A -> 1 + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.fir.txt new file mode 100644 index 00000000000..0d11593bd9b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.fir.txt @@ -0,0 +1,84 @@ +FILE: a.kt + public sealed class Base : R|kotlin/Any| { + private constructor(): R|Base| { + super() + } + + } + public final class A : R|Base| { + public constructor(): R|A| { + super() + } + + } +FILE: b.kt + public final object B : R|Base| { + private constructor(): R|B| { + super() + } + + } +FILE: c.kt + public final fun test_1(base: R|Base|): R|kotlin/Unit| { + lval x: R|kotlin/Unit| = when (R|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + } + + lval y: R|kotlin/Unit| = when (R|/base|) { + ==($subj$, Q|B|) -> { + Int(1) + } + } + + lval z: R|kotlin/Int| = when (R|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + ==($subj$, Q|B|) -> { + Int(2) + } + } + + } + public final fun test_2(base: R|Base?|): R|kotlin/Unit| { + lval x: R|kotlin/Unit| = when (R|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + ($subj$ is R|B|) -> { + Int(2) + } + } + + lval y: R|kotlin/Unit| = when (R|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + ==($subj$, Q|B|) -> { + Int(2) + } + } + + lval z: R|kotlin/Int| = when (R|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + ==($subj$, Q|B|) -> { + Int(2) + } + ==($subj$, Null(null)) -> { + Int(3) + } + } + + } + public final fun test_3(base: R|Base|): R|kotlin/Unit| { + when (R|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt new file mode 100644 index 00000000000..9300b82cb1f --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt @@ -0,0 +1,50 @@ +// FILE: a.kt + +sealed class Base + +class A : Base + +// FILE: b.kt + +object B : Base() + +// FILE: c.kt + +fun test_1(base: Base) { + val x = when (base) { + is A -> 1 + } + + val y = when (base) { + B -> 1 + } + + val z = when (base) { + is A -> 1 + B -> 2 + } +} + +fun test_2(base: Base?) { + val x = when (base) { + is A -> 1 + is B -> 2 + } + + val y = when (base) { + is A -> 1 + B -> 2 + } + + val z = when (base) { + is A -> 1 + B -> 2 + null -> 3 + } +} + +fun test_3(base: Base) { + when (base) { + is A -> 1 + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.dot b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.dot similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.dot rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.dot diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt similarity index 78% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt index ca517f63c3d..f6a79b2e097 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt @@ -1,5 +1,5 @@ fun test_1(b: Boolean) { - val x = when (b) { + val x = when (b) { true -> 1 } val y = when (b) { @@ -13,7 +13,7 @@ fun test_1(b: Boolean) { } fun test_2(b: Boolean?) { - val x = when (b) { + val x = when (b) { true -> 1 false -> 2 } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt similarity index 84% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt index c502f35e046..ac2e4c7bbb1 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt @@ -3,12 +3,12 @@ enum class Enum { } fun test_1(e: Enum) { - val a = when (e) { + val a = when (e) { Enum.A -> 1 Enum.B -> 2 } - val b = when (e) { + val b = when (e) { Enum.A -> 1 Enum.B -> 2 is String -> 3 @@ -27,7 +27,7 @@ fun test_1(e: Enum) { } fun test_2(e: Enum?) { - val a = when (e) { + val a = when (e) { Enum.A -> 1 Enum.B -> 2 Enum.C -> 3 diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt similarity index 89% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt index ab00bc6dab8..463216e5e5f 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt @@ -7,12 +7,12 @@ public enum JavaEnum { // FILE: main.kt fun test_1(e: JavaEnum) { - val a = when (e) { + val a = when (e) { JavaEnum.A -> 1 JavaEnum.B -> 2 }.plus(0) - val b = when (e) { + val b = when (e) { JavaEnum.A -> 1 JavaEnum.B -> 2 is String -> 3 @@ -31,7 +31,7 @@ fun test_1(e: JavaEnum) { } fun test_2(e: JavaEnum?) { - val a = when (e) { + val a = when (e) { JavaEnum.A -> 1 JavaEnum.B -> 2 JavaEnum.C -> 3 diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt similarity index 86% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt index 78547c73258..c37b08fc716 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt @@ -7,12 +7,12 @@ sealed class Base { class C : Base() fun test_1(e: Base) { - val a = when (e) { + val a = when (e) { is Base.A -> 1 is Base.A.B -> 2 } - val b = when (e) { + val b = when (e) { is Base.A -> 1 is Base.A.B -> 2 is String -> 3 @@ -31,7 +31,7 @@ fun test_1(e: Base) { } fun test_2(e: Base?) { - val a = when (e) { + val a = when (e) { is Base.A -> 1 is Base.A.B -> 2 is C -> 3 diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt similarity index 83% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt index 523b7eca50a..7ed050ea810 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt @@ -32,23 +32,23 @@ fun test_1(e: A) { } fun test_2(e: A) { - val a = when (e) { + val a = when (e) { is D -> 1 is E -> 2 }.plus(0) - val b = when (e) { + val b = when (e) { is B -> 1 is D -> 2 is E -> 3 }.plus(0) - val c = when (e) { + val c = when (e) { is B -> 1 is D -> 2 }.plus(0) - val d = when (e) { + val d = when (e) { is C -> 1 }.plus(0) } diff --git a/compiler/fir/analysis-tests/testData/resolve/whenElse.kt b/compiler/fir/analysis-tests/testData/resolve/whenElse.kt index 831c7f173ab..8dcd09a23e6 100644 --- a/compiler/fir/analysis-tests/testData/resolve/whenElse.kt +++ b/compiler/fir/analysis-tests/testData/resolve/whenElse.kt @@ -16,12 +16,12 @@ fun get(f: Boolean) = if (f) {A.A1} else {""} fun case2() { val flag: Any = get(false) //string - val l1 = when (flag!!) { // should be NO_ELSE_IN_WHEN + val l1 = when (flag!!) { // should be NO_ELSE_IN_WHEN A.A1 -> B() A.A2 -> B() } - val l2 = when (flag) {// should be NO_ELSE_IN_WHEN + val l2 = when (flag) {// should be NO_ELSE_IN_WHEN A.A1 -> B() A.A2 -> B() } @@ -30,12 +30,12 @@ fun get(f: Boolean) = if (f) {A.A1} else {""} fun case2() { val flag: Any = get(true) //A - val l1 = when (flag!!) {// should be NO_ELSE_IN_WHEN + val l1 = when (flag!!) {// should be NO_ELSE_IN_WHEN A.A1 -> B() A.A2 -> B() } - val l2 = when (flag) {// should be NO_ELSE_IN_WHEN + val l2 = when (flag) {// should be NO_ELSE_IN_WHEN A.A1 -> B() A.A2 -> B() } @@ -44,12 +44,12 @@ fun get(f: Boolean) = if (f) {A.A1} else {""} fun case3() { val flag = "" //A - val l1 = when (flag!!) {// should be NO_ELSE_IN_WHEN + val l1 = when (flag!!) {// should be NO_ELSE_IN_WHEN A.A1 -> B() //should be INCOMPATIBLE_TYPES A.A2 -> B() //should be INCOMPATIBLE_TYPES } - val l2 = when (flag) {// should be NO_ELSE_IN_WHEN + val l2 = when (flag) {// should be NO_ELSE_IN_WHEN A.A1 -> B() //should be INCOMPATIBLE_TYPES A.A2 -> B() //should be INCOMPATIBLE_TYPES } diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 604282878a9..f7da3ebcfff 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -158,54 +158,6 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/enumWithCompanion.kt"); } - @Test - @TestMetadata("exhaustiveWhenAndDNNType.kt") - public void testExhaustiveWhenAndDNNType() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt"); - } - - @Test - @TestMetadata("exhaustiveWhenAndFlexibleType.kt") - public void testExhaustiveWhenAndFlexibleType() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt"); - } - - @Test - @TestMetadata("exhaustiveness_boolean.kt") - public void testExhaustiveness_boolean() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt"); - } - - @Test - @TestMetadata("exhaustiveness_enum.kt") - public void testExhaustiveness_enum() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt"); - } - - @Test - @TestMetadata("exhaustiveness_enumJava.kt") - public void testExhaustiveness_enumJava() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt"); - } - - @Test - @TestMetadata("exhaustiveness_sealedClass.kt") - public void testExhaustiveness_sealedClass() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt"); - } - - @Test - @TestMetadata("exhaustiveness_sealedObject.kt") - public void testExhaustiveness_sealedObject() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt"); - } - - @Test - @TestMetadata("exhaustiveness_sealedSubClass.kt") - public void testExhaustiveness_sealedSubClass() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt"); - } - @Test @TestMetadata("extension.kt") public void testExtension() throws Exception { @@ -1466,6 +1418,108 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { } } + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness") + @TestDataPath("$PROJECT_ROOT") + public class Exhaustiveness { + @Test + public void testAllFilesPresentInExhaustiveness() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative") + @TestDataPath("$PROJECT_ROOT") + public class Negative { + @Test + public void testAllFilesPresentInNegative() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("missingBooleanBranch.kt") + public void testMissingBooleanBranch() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt"); + } + + @Test + @TestMetadata("missingElse.kt") + public void testMissingElse() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt"); + } + + @Test + @TestMetadata("missingEnumEntry.kt") + public void testMissingEnumEntry() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt"); + } + + @Test + @TestMetadata("missingSealedInheritor.kt") + public void testMissingSealedInheritor() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt"); + } + } + + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive") + @TestDataPath("$PROJECT_ROOT") + public class Positive { + @Test + public void testAllFilesPresentInPositive() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("exhaustiveWhenAndDNNType.kt") + public void testExhaustiveWhenAndDNNType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt"); + } + + @Test + @TestMetadata("exhaustiveWhenAndFlexibleType.kt") + public void testExhaustiveWhenAndFlexibleType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt"); + } + + @Test + @TestMetadata("exhaustiveness_boolean.kt") + public void testExhaustiveness_boolean() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt"); + } + + @Test + @TestMetadata("exhaustiveness_enum.kt") + public void testExhaustiveness_enum() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt"); + } + + @Test + @TestMetadata("exhaustiveness_enumJava.kt") + public void testExhaustiveness_enumJava() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt"); + } + + @Test + @TestMetadata("exhaustiveness_sealedClass.kt") + public void testExhaustiveness_sealedClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt"); + } + + @Test + @TestMetadata("exhaustiveness_sealedObject.kt") + public void testExhaustiveness_sealedObject() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt"); + } + + @Test + @TestMetadata("exhaustiveness_sealedSubClass.kt") + public void testExhaustiveness_sealedSubClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt"); + } + } + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 2324378a3ec..ea8708480aa 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -161,54 +161,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/enumWithCompanion.kt"); } - @Test - @TestMetadata("exhaustiveWhenAndDNNType.kt") - public void testExhaustiveWhenAndDNNType() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt"); - } - - @Test - @TestMetadata("exhaustiveWhenAndFlexibleType.kt") - public void testExhaustiveWhenAndFlexibleType() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt"); - } - - @Test - @TestMetadata("exhaustiveness_boolean.kt") - public void testExhaustiveness_boolean() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt"); - } - - @Test - @TestMetadata("exhaustiveness_enum.kt") - public void testExhaustiveness_enum() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt"); - } - - @Test - @TestMetadata("exhaustiveness_enumJava.kt") - public void testExhaustiveness_enumJava() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt"); - } - - @Test - @TestMetadata("exhaustiveness_sealedClass.kt") - public void testExhaustiveness_sealedClass() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt"); - } - - @Test - @TestMetadata("exhaustiveness_sealedObject.kt") - public void testExhaustiveness_sealedObject() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt"); - } - - @Test - @TestMetadata("exhaustiveness_sealedSubClass.kt") - public void testExhaustiveness_sealedSubClass() throws Exception { - runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt"); - } - @Test @TestMetadata("extension.kt") public void testExtension() throws Exception { @@ -1478,6 +1430,111 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos } } + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness") + @TestDataPath("$PROJECT_ROOT") + @Execution(ExecutionMode.SAME_THREAD) + public class Exhaustiveness { + @Test + public void testAllFilesPresentInExhaustiveness() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative") + @TestDataPath("$PROJECT_ROOT") + @Execution(ExecutionMode.SAME_THREAD) + public class Negative { + @Test + public void testAllFilesPresentInNegative() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("missingBooleanBranch.kt") + public void testMissingBooleanBranch() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt"); + } + + @Test + @TestMetadata("missingElse.kt") + public void testMissingElse() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt"); + } + + @Test + @TestMetadata("missingEnumEntry.kt") + public void testMissingEnumEntry() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt"); + } + + @Test + @TestMetadata("missingSealedInheritor.kt") + public void testMissingSealedInheritor() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt"); + } + } + + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive") + @TestDataPath("$PROJECT_ROOT") + @Execution(ExecutionMode.SAME_THREAD) + public class Positive { + @Test + public void testAllFilesPresentInPositive() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("exhaustiveWhenAndDNNType.kt") + public void testExhaustiveWhenAndDNNType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt"); + } + + @Test + @TestMetadata("exhaustiveWhenAndFlexibleType.kt") + public void testExhaustiveWhenAndFlexibleType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt"); + } + + @Test + @TestMetadata("exhaustiveness_boolean.kt") + public void testExhaustiveness_boolean() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt"); + } + + @Test + @TestMetadata("exhaustiveness_enum.kt") + public void testExhaustiveness_enum() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt"); + } + + @Test + @TestMetadata("exhaustiveness_enumJava.kt") + public void testExhaustiveness_enumJava() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt"); + } + + @Test + @TestMetadata("exhaustiveness_sealedClass.kt") + public void testExhaustiveness_sealedClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt"); + } + + @Test + @TestMetadata("exhaustiveness_sealedObject.kt") + public void testExhaustiveness_sealedObject() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt"); + } + + @Test + @TestMetadata("exhaustiveness_sealedSubClass.kt") + public void testExhaustiveness_sealedSubClass() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt"); + } + } + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt index 0088e1d7b9f..add59c21a70 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt @@ -6,11 +6,7 @@ package org.jetbrains.kotlin.fir.checkers.generator import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.expressions.FirFunctionCall -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression -import org.jetbrains.kotlin.fir.expressions.FirStatement -import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment -import org.jetbrains.kotlin.fir.expressions.FirTryExpression +import org.jetbrains.kotlin.fir.expressions.* import java.io.File fun main(args: Array) { @@ -23,6 +19,7 @@ fun main(args: Array) { alias("FunctionCallChecker") alias("VariableAssignmentChecker") alias("TryExpressionChecker") + alias("WhenExpressionChecker") } val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration" diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt index f4e8d19e20a..f3e5f53d1bf 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt @@ -23,12 +23,15 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() { get() = _variableAssignmentCheckers override val tryExpressionCheckers: Set get() = _tryExpressionCheckers + override val whenExpressionCheckers: Set + get() = _whenExpressionCheckers private val _basicExpressionCheckers: MutableSet = mutableSetOf() private val _qualifiedAccessCheckers: MutableSet = mutableSetOf() private val _functionCallCheckers: MutableSet = mutableSetOf() private val _variableAssignmentCheckers: MutableSet = mutableSetOf() private val _tryExpressionCheckers: MutableSet = mutableSetOf() + private val _whenExpressionCheckers: MutableSet = mutableSetOf() @CheckersComponentInternal internal fun register(checkers: ExpressionCheckers) { @@ -37,5 +40,6 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() { _functionCallCheckers += checkers.allFunctionCallCheckers _variableAssignmentCheckers += checkers.allVariableAssignmentCheckers _tryExpressionCheckers += checkers.allTryExpressionCheckers + _whenExpressionCheckers += checkers.allWhenExpressionCheckers } } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt index 72e167d29e2..116e76cfb52 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt @@ -22,10 +22,12 @@ abstract class ExpressionCheckers { open val functionCallCheckers: Set = emptySet() open val variableAssignmentCheckers: Set = emptySet() open val tryExpressionCheckers: Set = emptySet() + open val whenExpressionCheckers: Set = emptySet() @CheckersComponentInternal internal val allBasicExpressionCheckers: Set get() = basicExpressionCheckers @CheckersComponentInternal internal val allQualifiedAccessCheckers: Set get() = qualifiedAccessCheckers + allBasicExpressionCheckers @CheckersComponentInternal internal val allFunctionCallCheckers: Set get() = functionCallCheckers + allQualifiedAccessCheckers @CheckersComponentInternal internal val allVariableAssignmentCheckers: Set get() = variableAssignmentCheckers + allBasicExpressionCheckers @CheckersComponentInternal internal val allTryExpressionCheckers: Set get() = tryExpressionCheckers + allBasicExpressionCheckers + @CheckersComponentInternal internal val allWhenExpressionCheckers: Set get() = whenExpressionCheckers + allBasicExpressionCheckers } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt index 3f7f70d9f3d..b0c400b7185 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt @@ -15,9 +15,11 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirTryExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment +import org.jetbrains.kotlin.fir.expressions.FirWhenExpression typealias FirBasicExpressionChecker = FirExpressionChecker typealias FirQualifiedAccessChecker = FirExpressionChecker typealias FirFunctionCallChecker = FirExpressionChecker typealias FirVariableAssignmentChecker = FirExpressionChecker typealias FirTryExpressionChecker = FirExpressionChecker +typealias FirWhenExpressionChecker = FirExpressionChecker diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt new file mode 100644 index 00000000000..d48242f3b0f --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.expression + +import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.expressions.FirWhenExpression + +object FirExhaustiveWhenChecker : FirWhenExpressionChecker() { + override fun check(expression: FirWhenExpression, context: CheckerContext, reporter: DiagnosticReporter) { + // TODO: add reporting of proper missing clauses, see class WhenMissingCase + if (expression.usedAsExpression && !expression.isExhaustive) { + val factory = if (expression.source?.isIfExpression == true) { + FirErrors.INVALID_IF_AS_EXPRESSION + } else { + FirErrors.NO_ELSE_IN_WHEN + } + reporter.reportOn(expression.source, factory, context) + } + } + + private val FirSourceElement.isIfExpression: Boolean + get() = elementType == KtNodeTypes.IF +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt index ba5376b9c2a..ba53b856b84 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt @@ -53,7 +53,7 @@ class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollect } override fun visitWhenExpression(whenExpression: FirWhenExpression, data: CheckerContext) { - checkers.basicExpressionCheckers.check(whenExpression, data, reporter) + checkers.whenExpressionCheckers.check(whenExpression, data, reporter) } override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: CheckerContext) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index d62a2cd707d..6b5de471d3b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -84,6 +84,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_REQUI import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_IF_AS_EXPRESSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LEAKED_IN_PLACE_LAMBDA import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LOCAL_ANNOTATION_CLASS_ERROR @@ -100,6 +101,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRI import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_TYPE_FOR_TYPE_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER @@ -501,6 +503,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { // RENDER_TYPE //) + // When expressions + map.put(NO_ELSE_IN_WHEN, "''when'' expression must be exhaustive") + map.put(INVALID_IF_AS_EXPRESSION, "'if' must have both main and 'else' branches if used as an expression") + // Extended checkers group map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier") map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier") diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 0ac8ab7e8c9..8dbba130ef8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -230,6 +230,10 @@ object FirErrors { // TODO: val UNSAFE_OPERATOR_CALL by ... // TODO: val UNEXPECTED_SAFE_CALL by ... + // When expressions + val NO_ELSE_IN_WHEN by error0(SourceElementPositioningStrategies.WHEN_EXPRESSION) + val INVALID_IF_AS_EXPRESSION by error0(SourceElementPositioningStrategies.IF_EXPRESSION) + // Extended checkers group val REDUNDANT_VISIBILITY_MODIFIER by warning0(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val REDUNDANT_MODALITY_MODIFIER by warning0(SourceElementPositioningStrategies.MODALITY_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index dd80267b25a..f4b21c77cbb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -334,6 +334,28 @@ object LightTreePositioningStrategies { return super.mark(node, startOffset, endOffset, tree) } } + + val WHEN_EXPRESSION = object : LightTreePositioningStrategy() { + override fun mark( + node: LighterASTNode, + startOffset: Int, + endOffset: Int, + tree: FlyweightCapableTreeStructure + ): List { + return markElement(tree.whenKeyword(node) ?: node, startOffset, endOffset, tree, node) + } + } + + val IF_EXPRESSION = object : LightTreePositioningStrategy() { + override fun mark( + node: LighterASTNode, + startOffset: Int, + endOffset: Int, + tree: FlyweightCapableTreeStructure + ): List { + return markElement(tree.ifKeyword(node) ?: node, startOffset, endOffset, tree, node) + } + } } fun FirSourceElement.hasValOrVar(): Boolean = @@ -354,6 +376,12 @@ private fun FlyweightCapableTreeStructure.dotOperator(node: Ligh private fun FlyweightCapableTreeStructure.initKeyword(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtTokens.INIT_KEYWORD) +private fun FlyweightCapableTreeStructure.whenKeyword(node: LighterASTNode): LighterASTNode? = + findChildByType(node, KtTokens.WHEN_KEYWORD) + +private fun FlyweightCapableTreeStructure.ifKeyword(node: LighterASTNode): LighterASTNode? = + findChildByType(node, KtTokens.IF_KEYWORD) + private fun FlyweightCapableTreeStructure.nameIdentifier(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtTokens.IDENTIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt index 86c42f79947..4d4e326d73f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt @@ -102,4 +102,14 @@ object SourceElementPositioningStrategies { LightTreePositioningStrategies.DOT_BY_SELECTOR, PositioningStrategies.DOT_BY_SELECTOR ) -} \ No newline at end of file + + val WHEN_EXPRESSION = SourceElementPositioningStrategy( + LightTreePositioningStrategies.WHEN_EXPRESSION, + PositioningStrategies.WHEN_EXPRESSION + ) + + val IF_EXPRESSION = SourceElementPositioningStrategy( + LightTreePositioningStrategies.IF_EXPRESSION, + PositioningStrategies.IF_EXPRESSION + ) +} diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt index 4ffda04a3ec..fb52cf9a047 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt @@ -28,4 +28,8 @@ object CommonExpressionCheckers : ExpressionCheckers() { override val tryExpressionCheckers: Set = setOf( FirCatchParameterChecker ) + + override val whenExpressionCheckers: Set = setOf( + FirExhaustiveWhenChecker + ) } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index c5250d5a05f..43a3f9b436e 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -1105,7 +1105,10 @@ class ExpressionsConverter( private val LighterASTNode.usedAsExpression: Boolean get() { - val parent = getParent() ?: return true + var parent = getParent() ?: return true + if (parent.elementType == ANNOTATED_EXPRESSION) { + parent = parent.getParent() ?: return true + } val parentTokenType = parent.tokenType if (parentTokenType == BLOCK) return false if (parentTokenType == ELSE || parentTokenType == WHEN_ENTRY) { diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 7c960eebca1..834fc288308 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -1625,6 +1625,10 @@ class RawFirBuilder( private val KtExpression.usedAsExpression: Boolean get() { + var parent = parent + if (parent.elementType == KtNodeTypes.ANNOTATED_EXPRESSION) { + parent = parent.parent + } if (parent is KtBlockExpression) return false when (parent.elementType) { KtNodeTypes.ELSE, KtNodeTypes.WHEN_ENTRY -> { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 14fd5581a38..65684cefd04 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -507,6 +507,13 @@ object PositioningStrategies { } } + @JvmField + val IF_EXPRESSION: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: KtIfExpression): List { + return markElement(element.ifKeyword) + } + } + @JvmField val WHEN_CONDITION_IN_RANGE: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: KtWhenConditionInRange): List { diff --git a/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt b/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt index 6a62617d900..14ccbb2caa7 100644 --- a/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt +++ b/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt @@ -72,7 +72,7 @@ fun main1() { 1."sdf" 1.{} - 1.if (true) {} + 1.if (true) {} } fun test() { diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt index 628041e7526..8a956ae6273 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt @@ -70,7 +70,7 @@ fun blockReturnValueTypeMatch1() : Int { return if (1 > 2) 1.0 else 2.0 } fun blockReturnValueTypeMatch2() : Int { - return if (1 > 2) 1 + return if (1 > 2) 1 } fun blockReturnValueTypeMatch3() : Int { return if (1 > 2) else 1 @@ -106,7 +106,7 @@ fun blockReturnValueTypeMatch9() : Int { 1.0 } fun blockReturnValueTypeMatch10() : Int { - return if (1 > 2) + return if (1 > 2) 1 } fun blockReturnValueTypeMatch11() : Int { diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1185enums.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1185enums.fir.kt index 80b24b11bdc..48a32d9ed13 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1185enums.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1185enums.fir.kt @@ -29,7 +29,7 @@ fun foo(d: Direction) = when(d) { //no 'else' should be requested Direction.EAST -> 4 } -fun foo1(d: Direction) = when(d) { +fun foo1(d: Direction) = when(d) { Direction.NORTH -> 1 Direction.SOUTH -> 2 Direction.WEST -> 3 @@ -41,7 +41,7 @@ fun bar(c: Color) = when (c) { Color.BLUE -> 3 } -fun bar1(c: Color) = when (c) { +fun bar1(c: Color) = when (c) { Color.RED -> 1 Color.GREEN -> 2 -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/controlStructures/emptyIf.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/emptyIf.fir.kt deleted file mode 100644 index 5da2c7adbbe..00000000000 --- a/compiler/testData/diagnostics/tests/controlStructures/emptyIf.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -fun foo(x: Unit) = x - -fun test() { - if (false); - if (true); - - val x = if (false); - foo(x) - - val y: Unit = if (false); - foo(y) - - foo({if (1==1);}()) - - return if (true); -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt b/compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt index 13ce5412108..e12b774f2dd 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL fun foo(x: Unit) = x fun test() { diff --git a/compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.fir.kt index bd173b19cde..280f15a6478 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.fir.kt @@ -11,7 +11,7 @@ fun testMixedIfAndWhen() = else 1 true -> if (true) 42 else println() - else -> if (true) println() + else -> if (true) println() } else println() @@ -28,4 +28,4 @@ fun testWrappedExpressions() = } else { (((((42)) + 1))) - } \ No newline at end of file + } diff --git a/compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.fir.kt index ee00a4e882d..263daaaa536 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.fir.kt @@ -11,21 +11,21 @@ val mlist = MList() fun work() {} -val xx1 = if (true) 42 -val xx2: Unit = if (true) 42 -val xx3 = idAny(if (true) 42) -val xx4 = id(if (true) 42) -val xx5 = idUnit(if (true) 42) -val xx6 = null ?: if (true) 42 -val xx7 = "" + if (true) 42 +val xx1 = if (true) 42 +val xx2: Unit = if (true) 42 +val xx3 = idAny(if (true) 42) +val xx4 = id(if (true) 42) +val xx5 = idUnit(if (true) 42) +val xx6 = null ?: if (true) 42 +val xx7 = "" + if (true) 42 -val wxx1 = when { true -> 42 } -val wxx2: Unit = when { true -> 42 } -val wxx3 = idAny(when { true -> 42 }) -val wxx4 = id(when { true -> 42 }) -val wxx5 = idUnit(when { true -> 42 }) -val wxx6 = null ?: when { true -> 42 } -val wxx7 = "" + when { true -> 42 } +val wxx1 = when { true -> 42 } +val wxx2: Unit = when { true -> 42 } +val wxx3 = idAny(when { true -> 42 }) +val wxx4 = id(when { true -> 42 }) +val wxx5 = idUnit(when { true -> 42 }) +val wxx6 = null ?: when { true -> 42 } +val wxx7 = "" + when { true -> 42 } val fn1 = { if (true) 42 } val fn2 = { if (true) mlist.add() } @@ -41,24 +41,24 @@ val ufn4: () -> Unit = { when { true -> 42 } } val ufn5: () -> Unit = { when { true -> mlist.add() } } val ufn6: () -> Unit = { when { true -> work() } } -fun f1() = if (true) work() -fun f2() = if (true) mlist.add() -fun f3() = if (true) 42 -fun f4(): Unit = if (true) work() -fun f5(): Unit = if (true) mlist.add() -fun f6(): Unit = if (true) 42 -fun g1() = when { true -> work() } -fun g2() = when { true -> mlist.add() } -fun g3() = when { true -> 42 } -fun g4(): Unit = when { true -> work() } -fun g5(): Unit = when { true -> mlist.add() } -fun g6(): Unit = when { true -> 42 } +fun f1() = if (true) work() +fun f2() = if (true) mlist.add() +fun f3() = if (true) 42 +fun f4(): Unit = if (true) work() +fun f5(): Unit = if (true) mlist.add() +fun f6(): Unit = if (true) 42 +fun g1() = when { true -> work() } +fun g2() = when { true -> mlist.add() } +fun g3() = when { true -> 42 } +fun g4(): Unit = when { true -> work() } +fun g5(): Unit = when { true -> mlist.add() } +fun g6(): Unit = when { true -> 42 } fun foo1(x: String?) { - "" + if (true) 42 + "" + if (true) 42 w@while (true) { - x ?: if (true) break - x ?: when { true -> break@w } + x ?: if (true) break + x ?: when { true -> break@w } } } diff --git a/compiler/testData/diagnostics/tests/controlStructures/improperElseInExpression.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/improperElseInExpression.fir.kt index c36cb381506..bc9b8f49d94 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/improperElseInExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/improperElseInExpression.fir.kt @@ -4,7 +4,7 @@ fun example() { val a = if (true) true else false val b = if (true) else false - val c = if (true) true + val c = if (true) true val d = if (true) true else; val e = if (true) {} else false val f = if (true) true else {} @@ -27,7 +27,7 @@ fun example() { }() fun t(): Boolean { - return if (true) true + return if (true) true } return if (true) true else {} diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt index 2588f6cc895..2aa1d500c0d 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt @@ -99,10 +99,10 @@ fun testImplicitCoercion() { else -> z-- } - var iff = if (true) { + var iff = if (true) { z = 34 } - val g = if (true) 4 + val g = if (true) 4 val h = if (false) 4 else {} bar(if (true) { diff --git a/compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.fir.kt index fc5d5665024..baa658b8210 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.fir.kt @@ -25,7 +25,7 @@ fun t1(x: Int) = when(x) { else -> 1 } -fun t5(x: Int) = when (x) { +fun t5(x: Int) = when (x) { is Int -> 1 2 -> 2 } diff --git a/compiler/testData/diagnostics/tests/dataFlow/EmptyIf.fir.kt b/compiler/testData/diagnostics/tests/dataFlow/EmptyIf.fir.kt index 4b3db89acdc..71a28eb64f4 100644 --- a/compiler/testData/diagnostics/tests/dataFlow/EmptyIf.fir.kt +++ b/compiler/testData/diagnostics/tests/dataFlow/EmptyIf.fir.kt @@ -18,7 +18,7 @@ fun f3(s: Number?) { } fun f4(s: Int?) { - var u = if (s!! == 42); - if (u == Unit) u = if (s == 239); + var u = if (s!! == 42); + if (u == Unit) u = if (s == 239); return u -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt b/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt index f1075938464..90242dc54a5 100644 --- a/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt +++ b/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt @@ -142,7 +142,7 @@ fun getStringLength(obj : Any) : Char? { } fun toInt(i: Int?): Int = if (i != null) i else 0 -fun illegalWhenBody(a: Any): Int = when(a) { +fun illegalWhenBody(a: Any): Int = when(a) { is Int -> a is String -> a } diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt index afef06f3764..c393564b456 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt @@ -13,11 +13,11 @@ fun test(x: Stmt): String = } fun test2(x: Stmt): String = - when (x) { + when (x) { is Expr -> "expr" } fun test3(x: Expr): String = - when (x) { + when (x) { is Stmt -> "stmt" - } \ No newline at end of file + } diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt index d19eb6011fc..fab86d219d0 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt @@ -15,7 +15,7 @@ sealed class Base { // No else required } - fun bar() = when (this) { + fun bar() = when (this) { is A -> 1 is B.B1 -> 2 } @@ -31,4 +31,4 @@ sealed class Base { A.A1 -> 2 is A.A2 -> 3 } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.fir.kt deleted file mode 100644 index 68a39439d7c..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.fir.kt +++ /dev/null @@ -1,24 +0,0 @@ -sealed class A -sealed class B : A() - -class C : B() -class D : B() - -fun test(a: A): Any { - return when (a) { - is C -> "" - is D -> "" - } -} - -fun test2(a: A): Any { - return when (a) { - is B -> "" - } -} - -fun test3(a: A): Any { - return when (a) { - is D -> "" - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.kt index 5991129f143..35acddf35c2 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class A sealed class B : A() diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.fir.kt deleted file mode 100644 index 5c46abf6f29..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.fir.kt +++ /dev/null @@ -1,47 +0,0 @@ -sealed class Sealed() { - object First: Sealed() - open class NonFirst: Sealed() { - class NonSecond: NonFirst() { - object Third: Sealed() - class NonThird: Sealed() { - object Fourth: NonFirst() - class Fifth: Sealed() - } - } - object Second: Sealed() - } -} - -fun foo(s: Sealed) = when(s) { - Sealed.First -> 1 - is Sealed.NonFirst -> 2 - Sealed.NonFirst.Second -> 4 - Sealed.NonFirst.NonSecond.Third -> 6 - is Sealed.NonFirst.NonSecond.NonThird -> 8 - is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10 - // no else required -} - -fun fooWithElse(s: Sealed) = when(s) { - Sealed.First -> 1 - Sealed.NonFirst.NonSecond.Third -> 6 - is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10 - else -> 0 -} - -fun fooWithoutElse(s: Sealed) = when(s) { - Sealed.First -> 1 - is Sealed.NonFirst -> 2 - Sealed.NonFirst.NonSecond.Third -> 6 - is Sealed.NonFirst.NonSecond.NonThird -> 8 - is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10 -} - -fun barWithoutElse(s: Sealed) = when(s) { - Sealed.First -> 1 - is Sealed.NonFirst -> 2 - Sealed.NonFirst.Second -> 4 - is Sealed.NonFirst.NonSecond.NonThird -> 8 - is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10 -} - diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.kt index b7afa1df5ac..58e1f50baf9 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class Sealed() { object First: Sealed() open class NonFirst: Sealed() { diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt deleted file mode 100644 index 302a7bd38d8..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt +++ /dev/null @@ -1,64 +0,0 @@ -// ISSUE: KT-13495 -// !DIAGNOSTICS: -UNUSED_VARIABLE -// !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage - -// FILE: Base.kt - -sealed class Base { - class A : Base() -} - -// FILE: B.kt - -class B : Base() - -// FILE: Container.kt - -class Containter { - class C : Base() - - inner class D : Base() -} - -// FILE: main.kt - -fun test_OK(base: Base) { - val x = when (base) { - is Base.A -> 1 - is B -> 2 - is Containter.C -> 3 - is Containter.D -> 4 - } -} - -fun test_error_1(base: Base) { - val x = when (base) { - is B -> 2 - is Containter.C -> 3 - is Containter.D -> 4 - } -} - -fun test_error_2(base: Base) { - val x = when (base) { - is Base.A -> 1 - is Containter.C -> 3 - is Containter.D -> 4 - } -} - -fun test_error_3(base: Base) { - val x = when (base) { - is Base.A -> 1 - is B -> 2 - is Containter.D -> 4 - } -} - -fun test_error_4(base: Base) { - val x = when (base) { - is Base.A -> 1 - is B -> 2 - is Containter.C -> 3 - } -} diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt index d72d40c9102..50bf4002221 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // ISSUE: KT-13495 // !DIAGNOSTICS: -UNUSED_VARIABLE // !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.fir.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.fir.kt deleted file mode 100644 index 9c5be055bd6..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.fir.kt +++ /dev/null @@ -1,14 +0,0 @@ -sealed class Sealed(val x: Int) { - object First: Sealed(12) - open class NonFirst(x: Int, val y: Int): Sealed(x) { - object Second: NonFirst(34, 2) - object Third: NonFirst(56, 3) - } -} - -fun foo(s: Sealed): Int { - return when(s) { - is Sealed.NonFirst -> 0 - } -} - diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.kt index 439de1ee3fe..1aebcb54486 100644 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.kt +++ b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class Sealed(val x: Int) { object First: Sealed(12) open class NonFirst(x: Int, val y: Int): Sealed(x) { diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.fir.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.fir.kt deleted file mode 100644 index 77cbfbf26c7..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.fir.kt +++ /dev/null @@ -1,14 +0,0 @@ -sealed class Sealed(val x: Int) { - object First: Sealed(12) - open class NonFirst(x: Int, val y: Int): Sealed(x) { - object Second: NonFirst(34, 2) - object Third: NonFirst(56, 3) - } -} - -fun foo(s: Sealed): Int { - return when(s) { - !is Sealed.NonFirst -> 1 - } -} - diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.kt index 0d02f2c6757..6ad07912e17 100644 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.kt +++ b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class Sealed(val x: Int) { object First: Sealed(12) open class NonFirst(x: Int, val y: Int): Sealed(x) { diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.fir.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.fir.kt deleted file mode 100644 index e2d3b79c3c0..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.fir.kt +++ /dev/null @@ -1,22 +0,0 @@ -sealed class Sealed(val x: Int) { - interface ITuple { - val x: Int - val y: Int - } - class Tuple(override val x: Int, override val y: Int): ITuple - object First: Sealed(12) - open class NonFirst(tuple: Tuple): Sealed(tuple.x), ITuple { - override val y: Int = tuple.y - object Second: NonFirst(Tuple(34, 2)) - class Third: NonFirst(Tuple(56, 3)) - } -} - -fun foo(s: Sealed): Int { - return when(s) { - is Sealed.First -> 1 - !is Sealed.ITuple -> 0 - // else required - } -} - diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.kt index d8f20b9c3fc..8b78455629e 100644 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.kt +++ b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class Sealed(val x: Int) { interface ITuple { val x: Int diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAnyCase.fir.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAnyCase.fir.kt index e9e4eed0755..fc235670129 100644 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAnyCase.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAnyCase.fir.kt @@ -7,7 +7,7 @@ sealed class Sealed { } fun foo(s: Sealed): Int { - return when(s) { + return when(s) { is Sealed.First -> 1 !is Any -> 0 } diff --git a/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt b/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt index c2d43bfb3cc..9aabfe0ddb5 100644 --- a/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt @@ -9,7 +9,7 @@ sealed class Tree { is Node -> this.left.max() } - fun maxIsClass(): Int = when(this) { + fun maxIsClass(): Int = when(this) { Empty -> -1 Leaf -> 0 is Node -> this.left.max() @@ -20,4 +20,4 @@ sealed class Tree { is Node -> this.left.max() else -> -1 } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.fir.kt b/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.fir.kt deleted file mode 100644 index 9271a1b4474..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.fir.kt +++ /dev/null @@ -1,11 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_EXPRESSION -sealed class Sealed { - -} - -fun foo(s: Sealed): Int { - return when(s) { - // We do not return anything, so else branch must be here - } -} - diff --git a/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.kt b/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.kt index ea45861d7cd..05304d09f67 100644 --- a/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.kt +++ b/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_EXPRESSION sealed class Sealed { diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt27221_irrelevantClasses.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/kt27221_irrelevantClasses.fir.kt index 337c36e7ba1..51270bfde33 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/kt27221_irrelevantClasses.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/kt27221_irrelevantClasses.fir.kt @@ -10,7 +10,7 @@ object CC : C() fun foo(a: A) { if (a is B) { if (a is C) { - val t = when (a) { + val t = when (a) { is CC -> "CC" } } @@ -20,9 +20,9 @@ fun foo(a: A) { fun foo2(a: A) { if (a is C) { if (a is B) { - val t = when (a) { + val t = when (a) { is CC -> "CC" } } } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.fir.kt new file mode 100644 index 00000000000..e1d79e1e21d --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.fir.kt @@ -0,0 +1,9 @@ +public fun foo(x: String?, y: String?): Int { + while (true) { + x ?: if (y == null) break + // y is nullable if x != null + y.length + } + // y is null because of the break + return y.length +} diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.kt index ef2399abbe4..520459f73a9 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL public fun foo(x: String?, y: String?): Int { while (true) { x ?: if (y == null) break @@ -7,4 +6,4 @@ public fun foo(x: String?, y: String?): Int { } // y is null because of the break return y.length -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/unit/nullableUnit.fir.kt b/compiler/testData/diagnostics/tests/unit/nullableUnit.fir.kt deleted file mode 100644 index 42d2f77036a..00000000000 --- a/compiler/testData/diagnostics/tests/unit/nullableUnit.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -fun foo() {} - -val x: Unit? = when ("A") { - "B" -> foo() -} diff --git a/compiler/testData/diagnostics/tests/unit/nullableUnit.kt b/compiler/testData/diagnostics/tests/unit/nullableUnit.kt index 03d7ed33876..2c886979558 100644 --- a/compiler/testData/diagnostics/tests/unit/nullableUnit.kt +++ b/compiler/testData/diagnostics/tests/unit/nullableUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL fun foo() {} val x: Unit? = when ("A") { diff --git a/compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.fir.kt b/compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.fir.kt index 31da011183f..830e0ff2104 100644 --- a/compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.fir.kt +++ b/compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.fir.kt @@ -12,7 +12,7 @@ enum class E { A, B } -fun test(e: E?) = when (e) { +fun test(e: E?) = when (e) { E.A -> 1 E.B -> 2 } diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.fir.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.fir.kt similarity index 54% rename from compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.fir.kt rename to compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.fir.kt index 0a39652a6fd..298acefd490 100644 --- a/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.fir.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.fir.kt @@ -1,18 +1,18 @@ /* - * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) + * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * - * SPEC VERSION: 0.1-152 + * SPEC VERSION: 0.1-313 * PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1 * expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 3 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 10 + * expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 4 + * expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 5 */ // See also: KT-3743 -fun foo(arg: Boolean?): String { - // Must be NOT exhaustive - return when(arg) { - true -> "truth" - false -> "falsehood" +fun foo(arg: Boolean): String { + // Must be exhaustive + return when(arg) { + 2 == 2 -> "truth" + 2 == 1 -> "falsehood" } } diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.kt index 3b0933f5354..11e7d5f8d1c 100644 --- a/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.fir.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.fir.kt index 278ee04bced..398609150ba 100644 --- a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.fir.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.fir.kt @@ -12,7 +12,7 @@ enum class MyEnum { } fun foo(x: MyEnum): Int { - return when (x) { + return when (x) { is MyEnum.A -> 1 is MyEnum.B -> 2 is MyEnum.C -> 3 diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.fir.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.fir.kt index 481970e4455..aaea91337b6 100644 --- a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.fir.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.fir.kt @@ -13,7 +13,7 @@ enum class MyEnum { } fun foo(x: MyEnum): Int { - return when (x) { + return when (x) { MyEnum.A -> 1 is MyEnum.B -> 2 is MyEnum.C -> 3 diff --git a/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.fir.kt b/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.fir.kt deleted file mode 100644 index 382c03583e0..00000000000 --- a/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) - * - * SPEC VERSION: 0.1-152 - * PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1 - * expressions, when-expression -> paragraph 9 -> sentence 2 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1 - */ - -fun foo(x: Int) { - val y: Unit = when (x) { - 2 -> {} - 3 -> {} - } - return y -} diff --git a/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.kt b/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.kt index d08e040bc97..21b7d43fe64 100644 --- a/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.kt +++ b/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.fir.kt b/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.fir.kt deleted file mode 100644 index 81081046fa7..00000000000 --- a/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.fir.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) - * - * SPEC VERSION: 0.1-152 - * PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1 - * expressions, when-expression -> paragraph 9 -> sentence 2 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1 - */ - -fun foo(x: Int): Any { - val v = when (x) { - 2 -> 0 - } - return v -} diff --git a/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.kt b/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.kt index 5cc1a2be78f..fd65ecfa23b 100644 --- a/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.kt +++ b/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.fir.kt b/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.fir.kt deleted file mode 100644 index 69423511de3..00000000000 --- a/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.fir.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) - * - * SPEC VERSION: 0.1-152 - * PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1 - * expressions, when-expression -> paragraph 9 -> sentence 2 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1 - */ - -fun foo(x: Int): Any { - return when (x) { - 2 -> 0 - } -} diff --git a/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.kt b/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.kt index 6822f03a47a..de869792156 100644 --- a/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.kt +++ b/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.fir.kt b/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.fir.kt deleted file mode 100644 index 94b8f840ec2..00000000000 --- a/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) - * - * SPEC VERSION: 0.1-152 - * PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1 - * expressions, when-expression -> paragraph 9 -> sentence 2 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1 - */ - - -fun foo(x: Int) { - return when (x) { - 2 -> {} - 3 -> {} - } -} diff --git a/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.kt b/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.kt index 4a5dbe3116a..8b60f0b072c 100644 --- a/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.kt +++ b/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.kt b/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.kt index 545d5c3cc55..1b798926dff 100644 --- a/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.kt +++ b/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.fir.kt b/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.fir.kt deleted file mode 100644 index c3014d5ef6f..00000000000 --- a/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.fir.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) - * - * SPEC VERSION: 0.1-152 - * PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 9 - */ - -// See KT-6399: exhaustive whens on platform enums - -// FILE: J.java - -public enum J { - A, B; - - public static J create() { - return J.A; - } -} - -// FILE: K.kt - -fun foo(): Int { - // When is not-exhaustive - return when (J.create()) { - J.A -> 1 - } -} diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.kt b/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.kt index b9480bf6cc4..bb9451bca98 100644 --- a/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.kt +++ b/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustiveWithNullabilityCheck.fir.kt b/compiler/testData/diagnostics/tests/when/NonExhaustiveWithNullabilityCheck.fir.kt index e0bcb365303..9e4351e95bc 100644 --- a/compiler/testData/diagnostics/tests/when/NonExhaustiveWithNullabilityCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/when/NonExhaustiveWithNullabilityCheck.fir.kt @@ -13,7 +13,7 @@ enum class X { A, B } fun foo(arg: X?): Int { if (arg != null) { - return when (arg) { + return when (arg) { X.B -> 2 } } diff --git a/compiler/testData/diagnostics/tests/when/TopLevelSealed.fir.kt b/compiler/testData/diagnostics/tests/when/TopLevelSealed.fir.kt deleted file mode 100644 index b7577c720de..00000000000 --- a/compiler/testData/diagnostics/tests/when/TopLevelSealed.fir.kt +++ /dev/null @@ -1,32 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_VARIABLE -/* - * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) - * - * SPEC VERSION: 0.1-152 - * PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1 - * expressions, when-expression -> paragraph 6 -> sentence 1 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 6 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 7 - * expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 8 - */ - -sealed class A { - class B: A() { - class C: A() - } -} - -class D: A() - -fun test(a: A) { - val nonExhaustive = when (a) { - is A.B -> "B" - is A.B.C -> "C" - } - - val exhaustive = when (a) { - is A.B -> "B" - is A.B.C -> "C" - is D -> "D" - } -} diff --git a/compiler/testData/diagnostics/tests/when/TopLevelSealed.kt b/compiler/testData/diagnostics/tests/when/TopLevelSealed.kt index 14d6fd04291..6581b1c9cc1 100644 --- a/compiler/testData/diagnostics/tests/when/TopLevelSealed.kt +++ b/compiler/testData/diagnostics/tests/when/TopLevelSealed.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) diff --git a/compiler/testData/diagnostics/tests/when/kt4434.fir.kt b/compiler/testData/diagnostics/tests/when/kt4434.fir.kt index 46abd84179d..8a378378379 100644 --- a/compiler/testData/diagnostics/tests/when/kt4434.fir.kt +++ b/compiler/testData/diagnostics/tests/when/kt4434.fir.kt @@ -27,7 +27,7 @@ fun foo(): Int { fun bar(): Int { val a = "a" if (a.length > 0) { - return when (a) { + return when (a) { "a" -> 1 } } diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.fir.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.fir.kt index 1be42fe50ee..bec1af3affc 100644 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.fir.kt +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.fir.kt @@ -38,4 +38,4 @@ fun test4() { 2 -> bar(x, y) } } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.fir.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.fir.kt deleted file mode 100644 index 882e2c17b76..00000000000 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -// !LANGUAGE: +VariableDeclarationInWhenSubject -// !DIAGNOSTICS: -UNUSED_VARIABLE - -enum class E { FIRST, SECOND } - -fun testSmartcastToEnumInSubjectInitializer1(e: E?) { - val x1 = when (val ne = e!!) { - E.FIRST -> "f" - E.SECOND -> "s" - } -} - -fun testSmartcastToEnumInSubjectInitializer2(e: E?) { - val x2 = when (val ne: Any = e!!) { // NB explicit type annotation - E.FIRST -> "f" - E.SECOND -> "s" - } -} diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt index 1b9f4988ed8..fe94c3c103b 100644 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +VariableDeclarationInWhenSubject // !DIAGNOSTICS: -UNUSED_VARIABLE diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.fir.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.fir.kt deleted file mode 100644 index 7e66946fe0b..00000000000 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.fir.kt +++ /dev/null @@ -1,20 +0,0 @@ -// !LANGUAGE: +VariableDeclarationInWhenSubject -// !DIAGNOSTICS: -UNUSED_VARIABLE - -sealed class Either -class Left : Either() -class Right : Either() - -fun testSmartcastToSealedInSubjectInitializer1(x: Any?) { - val y1 = when (val either = x as Either) { - is Left -> "L" - is Right -> "R" - } -} - -fun testSmartcastToSealedInSubjectInitializer2(x: Any?) { - val y2 = when (val either: Any = x as Either) { // NB explicit type annotation - is Left -> "L" - is Right -> "R" - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.kt index bde8ea93959..9fe474c40fc 100644 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.kt +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +VariableDeclarationInWhenSubject // !DIAGNOSTICS: -UNUSED_VARIABLE From abd1c8fb30a7046ac0054af70e3cf035d045ee41 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 16:07:40 +0300 Subject: [PATCH 051/153] [FIR] Move `sealedInheritors` declaration data to :fir:tree module --- .../fir/deserialization/ClassDeserialization.kt | 1 - .../kotlin/fir/serialization/FirElementSerializer.kt | 1 - .../FirSealedClassInheritorsProcessor.kt | 4 ---- .../kotlin/fir/declarations/SealedClassInheritors.kt | 12 ++++++++++++ 4 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/SealedClassInheritors.kt diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt index 5c0b05b084b..478fba4b5ba 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt @@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusIm import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCloneableSymbolProvider.Companion.CLONE import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCloneableSymbolProvider.Companion.CLONEABLE_CLASS_ID -import org.jetbrains.kotlin.fir.resolve.transformers.sealedInheritors import org.jetbrains.kotlin.fir.scopes.FirScopeProvider import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt index 4fbd57e802a..010aed0fe88 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType import org.jetbrains.kotlin.fir.resolve.inference.suspendFunctionTypeToFunctionTypeWithContinuation import org.jetbrains.kotlin.fir.resolve.toSymbol -import org.jetbrains.kotlin.fir.resolve.transformers.sealedInheritors import org.jetbrains.kotlin.fir.serialization.constant.EnumValue import org.jetbrains.kotlin.fir.serialization.constant.IntValue import org.jetbrains.kotlin.fir.serialization.constant.StringValue diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt index 98d86b67a48..2254c96a831 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt @@ -95,7 +95,3 @@ class FirSealedClassInheritorsProcessor( } } - -object SealedClassInheritorsKey : FirDeclarationDataKey() - -var FirRegularClass.sealedInheritors: List? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/SealedClassInheritors.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/SealedClassInheritors.kt new file mode 100644 index 00000000000..e16a6ad3498 --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/SealedClassInheritors.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.declarations + +import org.jetbrains.kotlin.name.ClassId + +object SealedClassInheritorsKey : FirDeclarationDataKey() + +var FirRegularClass.sealedInheritors: List? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey) From 96038e4b32f2c4ab86a12f5ac25c550ac8ab04a7 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 16:13:01 +0300 Subject: [PATCH 052/153] [FIR] Support java sealed class interop --- .../org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt | 8 ++++++++ .../java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt index 8251fc7d84b..179ce39b4c1 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.java import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -316,6 +317,13 @@ class JavaSymbolProvider( valueParametersForAnnotationConstructor = valueParametersForAnnotationConstructor ) } + }.apply { + if (modality == Modality.SEALED) { + sealedInheritors = javaClass.permittedTypes.mapNotNull { classifierType -> + val classifier = classifierType.classifier as? JavaClass + classifier?.let { JavaToKotlinClassMap.mapJavaToKotlin(it.fqName!!) } + } + } } private fun convertJavaFieldToFir( diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt index 19b2634eb67..368ae99b351 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt @@ -63,6 +63,14 @@ internal val JavaModifierListOwner.modality: Modality else -> Modality.OPEN } +internal val JavaClass.modality: Modality + get() = when { + isSealed -> Modality.SEALED + isAbstract -> Modality.ABSTRACT + isFinal -> Modality.FINAL + else -> Modality.OPEN + } + internal val JavaClass.classKind: ClassKind get() = when { isAnnotationType -> ClassKind.ANNOTATION_CLASS From ad677046a82b09e7cfb6d95a5b332fbc35fec930 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 4 Feb 2021 17:28:08 +0300 Subject: [PATCH 053/153] [FIR] Replace `isExhaustive` flag with `ExhaustivenessStatus` object --- .../expression/FirExhaustiveWhenChecker.kt | 1 + .../src/org/jetbrains/kotlin/fir/CopyUtils.kt | 2 +- .../FirWhenExhaustivenessTransformer.kt | 27 +++++++++---------- .../fir/expressions/FirWhenExpression.kt | 4 +-- .../builder/FirWhenExpressionBuilder.kt | 5 ++-- .../expressions/impl/FirWhenExpressionImpl.kt | 7 ++--- .../fir/expressions/ExhaustivenessStatus.kt | 24 +++++++++++++++++ .../fir/tree/generator/BuilderConfigurator.kt | 2 +- .../fir/tree/generator/NodeConfigurator.kt | 2 +- .../kotlin/fir/tree/generator/Types.kt | 2 ++ 10 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt index d48242f3b0f..3f229f9497b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.expressions.FirWhenExpression +import org.jetbrains.kotlin.fir.expressions.isExhaustive object FirExhaustiveWhenChecker : FirWhenExpressionChecker() { override fun check(expression: FirWhenExpression, context: CheckerContext, reporter: DiagnosticReporter) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt index 7d43c90ee06..cab6f986109 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/CopyUtils.kt @@ -138,7 +138,7 @@ fun FirWhenExpression.copy( typeRef = resultType this.annotations += annotations usedAsExpression = this@copy.usedAsExpression - isExhaustive = this@copy.isExhaustive + exhaustivenessStatus = this@copy.exhaustivenessStatus } fun FirTryExpression.copy( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt index 93fe1316437..5d79a86a14a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.utils.addToStdlib.runIf class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyResolveComponents) : FirTransformer() { override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { @@ -29,23 +28,23 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe } override fun transformWhenExpression(whenExpression: FirWhenExpression, data: Nothing?): CompositeTransformResult { - val resultExpression = processExhaustivenessCheck(whenExpression) ?: whenExpression - return resultExpression.compose() + processExhaustivenessCheck(whenExpression) + return whenExpression.compose() } - private fun processExhaustivenessCheck(whenExpression: FirWhenExpression): FirWhenExpression? { + private fun processExhaustivenessCheck(whenExpression: FirWhenExpression) { if (whenExpression.branches.any { it.condition is FirElseIfTrueCondition }) { - whenExpression.replaceIsExhaustive(true) - return whenExpression + whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.Exhaustive) + return } val typeRef = whenExpression.subjectVariable?.returnTypeRef ?: whenExpression.subject?.typeRef - ?: return null + ?: return // TODO: add some report logic about flexible type (see WHEN_ENUM_CAN_BE_NULL_IN_JAVA diagnostic in old frontend) val type = typeRef.coneType.lowerBoundIfFlexible() - val lookupTag = (type as? ConeLookupTagBasedType)?.lookupTag ?: return null + val lookupTag = (type as? ConeLookupTagBasedType)?.lookupTag ?: return val nullable = type.nullability == ConeNullability.NULLABLE val isExhaustive = when { ((lookupTag as? ConeClassLikeLookupTag)?.classId == bodyResolveComponents.session.builtinTypes.booleanType.id) -> { @@ -55,18 +54,18 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe whenExpression.branches.isEmpty() -> false else -> { - val klass = lookupTag.toSymbol(bodyResolveComponents.session)?.fir as? FirRegularClass ?: return null + val klass = lookupTag.toSymbol(bodyResolveComponents.session)?.fir as? FirRegularClass ?: return when { klass.classKind == ClassKind.ENUM_CLASS -> checkEnumExhaustiveness(whenExpression, klass, nullable) klass.modality == Modality.SEALED -> checkSealedClassExhaustiveness(whenExpression, klass, nullable) - else -> return null + else -> return } } } - - return runIf(isExhaustive) { - whenExpression.replaceIsExhaustive(true) - whenExpression + if (isExhaustive) { + whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.Exhaustive) + } else { + whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.NotExhaustive(listOf())) } } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWhenExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWhenExpression.kt index 807c8bf0aa6..54dcb8c6247 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWhenExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirWhenExpression.kt @@ -24,7 +24,7 @@ abstract class FirWhenExpression : FirExpression(), FirResolvable { abstract val subject: FirExpression? abstract val subjectVariable: FirVariable<*>? abstract val branches: List - abstract val isExhaustive: Boolean + abstract val exhaustivenessStatus: ExhaustivenessStatus? abstract val usedAsExpression: Boolean override fun accept(visitor: FirVisitor, data: D): R = visitor.visitWhenExpression(this, data) @@ -33,7 +33,7 @@ abstract class FirWhenExpression : FirExpression(), FirResolvable { abstract override fun replaceCalleeReference(newCalleeReference: FirReference) - abstract fun replaceIsExhaustive(newIsExhaustive: Boolean) + abstract fun replaceExhaustivenessStatus(newExhaustivenessStatus: ExhaustivenessStatus?) abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirWhenExpression diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirWhenExpressionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirWhenExpressionBuilder.kt index c2c8f8c2a15..8c1f741507e 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirWhenExpressionBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirWhenExpressionBuilder.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.declarations.FirVariable +import org.jetbrains.kotlin.fir.expressions.ExhaustivenessStatus import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch @@ -36,7 +37,7 @@ class FirWhenExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBui var subject: FirExpression? = null var subjectVariable: FirVariable<*>? = null val branches: MutableList = mutableListOf() - var isExhaustive: Boolean = false + var exhaustivenessStatus: ExhaustivenessStatus? = null var usedAsExpression: Boolean by kotlin.properties.Delegates.notNull() override fun build(): FirWhenExpression { @@ -48,7 +49,7 @@ class FirWhenExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBui subject, subjectVariable, branches, - isExhaustive, + exhaustivenessStatus, usedAsExpression, ) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWhenExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWhenExpressionImpl.kt index 79eaebe408a..adbc9991a88 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWhenExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirWhenExpressionImpl.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.expressions.impl import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.declarations.FirVariable +import org.jetbrains.kotlin.fir.expressions.ExhaustivenessStatus import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch @@ -28,7 +29,7 @@ internal class FirWhenExpressionImpl( override var subject: FirExpression?, override var subjectVariable: FirVariable<*>?, override val branches: MutableList, - override var isExhaustive: Boolean, + override var exhaustivenessStatus: ExhaustivenessStatus?, override val usedAsExpression: Boolean, ) : FirWhenExpression() { override fun acceptChildren(visitor: FirVisitor, data: D) { @@ -91,7 +92,7 @@ internal class FirWhenExpressionImpl( calleeReference = newCalleeReference } - override fun replaceIsExhaustive(newIsExhaustive: Boolean) { - isExhaustive = newIsExhaustive + override fun replaceExhaustivenessStatus(newExhaustivenessStatus: ExhaustivenessStatus?) { + exhaustivenessStatus = newExhaustivenessStatus } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt new file mode 100644 index 00000000000..50966403df1 --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.expressions + +import org.jetbrains.kotlin.name.ClassId + +sealed class ExhaustivenessStatus { + object Exhaustive : ExhaustivenessStatus() + class NotExhaustive(val reasons: List) : ExhaustivenessStatus() +} + +sealed class WhenMissingCase { + object Unknown : WhenMissingCase() + object NullIsMissing : WhenMissingCase() + class BooleanIsMissing(val value: Boolean) : WhenMissingCase() + class IsTypeCheckIsMissing(val classId: ClassId) : WhenMissingCase() + class EnumCheckIsMissing(val classId: ClassId) : WhenMissingCase() +} + +val FirWhenExpression.isExhaustive: Boolean + get() = exhaustivenessStatus == ExhaustivenessStatus.Exhaustive diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt index 20501be0b0a..9bf147a98e3 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt @@ -219,7 +219,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree } builder(whenExpression) { - defaultFalse("isExhaustive") + defaultNull("exhaustivenessStatus") default("calleeReference", "FirStubReference") useTypes(stubReferenceType) } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index 9be4b83fa77..d655c4b4282 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -587,7 +587,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +field("subject", expression, nullable = true).withTransform() +field("subjectVariable", variable.withArgs("F" to "*"), nullable = true) +fieldList("branches", whenBranch).withTransform() - +booleanField("isExhaustive", withReplace = true) + +field("exhaustivenessStatus", exhaustivenessStatusType, nullable = true, withReplace = true) +booleanField("usedAsExpression") needTransformOtherChildren() } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt index 2be2eeb4e63..38e16b2f88b 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt @@ -84,3 +84,5 @@ val firImplementationDetailType = generatedType("FirImplementationDetail") val declarationOriginType = generatedType("declarations", "FirDeclarationOrigin") val declarationAttributesType = generatedType("declarations", "FirDeclarationAttributes") val annotationResolveStatusType = generatedType("expressions", "FirAnnotationResolveStatus") + +val exhaustivenessStatusType = generatedType("expressions", "ExhaustivenessStatus") From 2a1c9283a477003d0428625740d0ff596bc1ef8b Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Sat, 6 Feb 2021 11:47:30 +0300 Subject: [PATCH 054/153] [FIR] Add useful util extensions for cone type --- .../kotlin/fir/types/ConeTypeUtils.kt | 20 +++++++++++++++++++ .../calls/CallableReferenceResolution.kt | 4 ++-- .../inference/PostponedArgumentsAnalyzer.kt | 4 ++-- .../jetbrains/kotlin/fir/types/TypeUtils.kt | 11 ++++++---- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt index e2683df9291..7062e884af3 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.types +import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.Variance @@ -55,3 +56,22 @@ fun ConeClassLikeType.replaceArgumentsWithStarProjections(): ConeClassLikeType { val newArguments = Array(typeArguments.size) { ConeStarProjection } return withArguments(newArguments) } + +val ConeKotlinType.isAny: Boolean get() = isBuiltinType(StandardClassIds.Any, false) +val ConeKotlinType.isNullableAny: Boolean get() = isBuiltinType(StandardClassIds.Any, true) +val ConeKotlinType.isNothing: Boolean get() = isBuiltinType(StandardClassIds.Nothing, false) +val ConeKotlinType.isNullableNothing: Boolean get() = isBuiltinType(StandardClassIds.Nothing, true) +val ConeKotlinType.isUnit: Boolean get() = isBuiltinType(StandardClassIds.Unit, false) +val ConeKotlinType.isBoolean: Boolean get() = isBuiltinType(StandardClassIds.Boolean, false) +val ConeKotlinType.isEnum: Boolean get() = isBuiltinType(StandardClassIds.Enum, false) +val ConeKotlinType.isArrayType: Boolean + get() { + return isBuiltinType(StandardClassIds.Array, false) || + StandardClassIds.primitiveArrayTypeByElementType.values.any { isBuiltinType(it, false) } + } + +private fun ConeKotlinType.isBuiltinType(classId: ClassId, isNullable: Boolean): Boolean { + + if (this !is ConeClassLikeType) return false + return lookupTag.classId == classId && type.isNullable == isNullable +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallableReferenceResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallableReferenceResolution.kt index 3fcf7709d64..c7c0e2ce9a4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallableReferenceResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallableReferenceResolution.kt @@ -226,7 +226,7 @@ private fun BodyResolveComponents.getCallableReferenceAdaptation( } } - val coercionStrategy = if (returnExpectedType.isUnit && !function.returnTypeRef.isUnit) + val coercionStrategy = if (returnExpectedType.isUnitOrFlexibleUnit && !function.returnTypeRef.isUnit) CoercionStrategy.COERCION_TO_UNIT else CoercionStrategy.NO_COERCION @@ -288,7 +288,7 @@ private enum class VarargMappingState { private fun FirFunction<*>.indexOf(valueParameter: FirValueParameter): Int = valueParameters.indexOf(valueParameter) -val ConeKotlinType.isUnit: Boolean +val ConeKotlinType.isUnitOrFlexibleUnit: Boolean get() { val type = this.lowerBoundIfFlexible() if (type.isNullable) return false diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArgumentsAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArgumentsAnalyzer.kt index 5bba7ca49e6..1e5395e994e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArgumentsAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArgumentsAnalyzer.kt @@ -168,14 +168,14 @@ class PostponedArgumentsAnalyzer( val lastExpression = lambda.atom.body?.statements?.lastOrNull() as? FirExpression var hasExpressionInReturnArguments = false // No constraint for return expressions of lambda if it has Unit return type. - val lambdaReturnType = lambda.returnType.let(substitute).takeUnless { it.isUnit } + val lambdaReturnType = lambda.returnType.let(substitute).takeUnless { it.isUnitOrFlexibleUnit } returnArguments.forEach { if (it !is FirExpression) return@forEach hasExpressionInReturnArguments = true // If it is the last expression, and the expected type is Unit, that expression will be coerced to Unit. // If the last expression is of Unit type, of course it's not coercion-to-Unit case. val lastExpressionCoercedToUnit = - it == lastExpression && expectedReturnType?.isUnit == true && !it.typeRef.coneType.isUnit + it == lastExpression && expectedReturnType?.isUnitOrFlexibleUnit == true && !it.typeRef.coneType.isUnitOrFlexibleUnit // No constraint for the last expression of lambda if it will be coerced to Unit. if (!lastExpressionCoercedToUnit) { candidate.resolveArgumentExpression( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index 7b2e341b402..b43f0ee261d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -7,13 +7,12 @@ package org.jetbrains.kotlin.fir.types import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility -import org.jetbrains.kotlin.fir.FirFakeSourceElementKind -import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.classId import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic -import org.jetbrains.kotlin.fir.fakeElement -import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef @@ -184,6 +183,10 @@ fun ConeKotlinType.isUnsafeVarianceType(session: FirSession): Boolean { return type.attributes.unsafeVarianceType != null } +fun ConeKotlinType.toSymbol(session: FirSession): AbstractFirBasedSymbol<*>? { + return (this as? ConeLookupTagBasedType)?.lookupTag?.toSymbol(session) +} + fun FirTypeRef.isUnsafeVarianceType(session: FirSession): Boolean { return coneTypeSafe()?.isUnsafeVarianceType(session) == true } From 18bde2c5422fbbfceaf3f50b844a585358c12fe7 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Sat, 6 Feb 2021 12:34:32 +0300 Subject: [PATCH 055/153] [FIR] Reimplement when exhaustiveness checker to fir it's logic with FE 1.0 --- .../exhaustiveness_sealedSubClass.fir.txt | 4 +- .../positive/exhaustiveness_sealedSubClass.kt | 4 +- .../expression/FirExhaustiveWhenChecker.kt | 10 +- .../diagnostics/FirDefaultErrorMessages.kt | 3 +- .../diagnostics/FirDiagnosticRenderers.kt | 13 + .../fir/analysis/diagnostics/FirErrors.kt | 3 +- .../FirWhenExhaustivenessTransformer.kt | 432 ++++++++++-------- .../fir/expressions/ExhaustivenessStatus.kt | 56 ++- .../tests/sealed/ExhaustiveOnRoot.fir.kt | 2 +- .../tests/sealed/ExhaustiveOnTree.fir.kt | 34 -- .../tests/sealed/ExhaustiveOnTree.kt | 1 + 11 files changed, 329 insertions(+), 233 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt index 1e4580f5d2f..db6cbd744a5 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt @@ -107,10 +107,10 @@ FILE: exhaustiveness_sealedSubClass.kt } } .#(Int(0)) - lval d: R|ERROR CLASS: Unresolved name: plus| = when (R|/e|) { + lval d: R|kotlin/Int| = when (R|/e|) { ($subj$ is R|C|) -> { Int(1) } } - .#(Int(0)) + .R|kotlin/Int.plus|(Int(0)) } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt index 7ed050ea810..9beeb8a7276 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt @@ -48,7 +48,7 @@ fun test_2(e: A) { is D -> 2 }.plus(0) - val d = when (e) { + val d = when (e) { is C -> 1 - }.plus(0) + }.plus(0) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt index 3f229f9497b..ace54dbcc92 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt @@ -11,19 +11,19 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.expressions.ExhaustivenessStatus import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.isExhaustive object FirExhaustiveWhenChecker : FirWhenExpressionChecker() { override fun check(expression: FirWhenExpression, context: CheckerContext, reporter: DiagnosticReporter) { - // TODO: add reporting of proper missing clauses, see class WhenMissingCase if (expression.usedAsExpression && !expression.isExhaustive) { - val factory = if (expression.source?.isIfExpression == true) { - FirErrors.INVALID_IF_AS_EXPRESSION + if (expression.source?.isIfExpression == true) { + reporter.reportOn(expression.source, FirErrors.INVALID_IF_AS_EXPRESSION, context) } else { - FirErrors.NO_ELSE_IN_WHEN + val missingCases = (expression.exhaustivenessStatus as ExhaustivenessStatus.NotExhaustive).reasons + reporter.reportOn(expression.source, FirErrors.NO_ELSE_IN_WHEN, missingCases, context) } - reporter.reportOn(expression.source, factory, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 6b5de471d3b..f1c711dfbea 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMB import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_STRING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VISIBILITY +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.WHEN_MISSING_CASES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_DELEGATED_PROPERTY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_WITH_BODY @@ -504,7 +505,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { //) // When expressions - map.put(NO_ELSE_IN_WHEN, "''when'' expression must be exhaustive") + map.put(NO_ELSE_IN_WHEN, "''when'' expression must be exhaustive, add necessary {0}", WHEN_MISSING_CASES) map.put(INVALID_IF_AS_EXPRESSION, "'if' must have both main and 'else' branches if used as an expression") // Extended checkers group diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt index 3e35205c1a9..b0627cd5e12 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.Renderer import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.WhenMissingCase import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.renderWithType import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol @@ -88,4 +89,16 @@ object FirDiagnosticRenderers { SYMBOL.render(symbol) } } + + private const val WHEN_MISSING_LIMIT = 7 + + val WHEN_MISSING_CASES = Renderer { missingCases: List -> + if (missingCases.firstOrNull() == WhenMissingCase.Unknown) { + "'else' branch" + } else { + val list = missingCases.joinToString(", ", limit = WHEN_MISSING_LIMIT) { "'$it'" } + val branches = if (missingCases.size > 1) "branches" else "branch" + "$list $branches or 'else' branch instead" + } + } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 8dbba130ef8..94b33f8e56a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration +import org.jetbrains.kotlin.fir.expressions.WhenMissingCase import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol @@ -231,7 +232,7 @@ object FirErrors { // TODO: val UNEXPECTED_SAFE_CALL by ... // When expressions - val NO_ELSE_IN_WHEN by error0(SourceElementPositioningStrategies.WHEN_EXPRESSION) + val NO_ELSE_IN_WHEN by error1>(SourceElementPositioningStrategies.WHEN_EXPRESSION) val INVALID_IF_AS_EXPRESSION by error0(SourceElementPositioningStrategies.IF_EXPRESSION) // Extended checkers group diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt index 5d79a86a14a..238d60a951c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt @@ -8,21 +8,34 @@ package org.jetbrains.kotlin.fir.resolve.transformers import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.LogicOperationKind.OR import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition -import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents -import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag -import org.jetbrains.kotlin.fir.resolve.toSymbol -import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.resolve.symbolProvider +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.visitors.* -import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.FirVisitor +import org.jetbrains.kotlin.fir.visitors.compose class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyResolveComponents) : FirTransformer() { + companion object { + private val exhaustivenessCheckers = listOf( + WhenOnBooleanExhaustivenessChecker, + WhenOnEnumExhaustivenessChecker, + WhenOnSealedClassExhaustivenessChecker + ) + } + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { throw IllegalArgumentException("Should not be there") } @@ -32,220 +45,279 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe return whenExpression.compose() } + @OptIn(ExperimentalStdlibApi::class) private fun processExhaustivenessCheck(whenExpression: FirWhenExpression) { if (whenExpression.branches.any { it.condition is FirElseIfTrueCondition }) { whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.Exhaustive) return } - val typeRef = whenExpression.subjectVariable?.returnTypeRef - ?: whenExpression.subject?.typeRef - ?: return - - // TODO: add some report logic about flexible type (see WHEN_ENUM_CAN_BE_NULL_IN_JAVA diagnostic in old frontend) - val type = typeRef.coneType.lowerBoundIfFlexible() - val lookupTag = (type as? ConeLookupTagBasedType)?.lookupTag ?: return - val nullable = type.nullability == ConeNullability.NULLABLE - val isExhaustive = when { - ((lookupTag as? ConeClassLikeLookupTag)?.classId == bodyResolveComponents.session.builtinTypes.booleanType.id) -> { - checkBooleanExhaustiveness(whenExpression, nullable) - } - - whenExpression.branches.isEmpty() -> false - - else -> { - val klass = lookupTag.toSymbol(bodyResolveComponents.session)?.fir as? FirRegularClass ?: return - when { - klass.classKind == ClassKind.ENUM_CLASS -> checkEnumExhaustiveness(whenExpression, klass, nullable) - klass.modality == Modality.SEALED -> checkSealedClassExhaustiveness(whenExpression, klass, nullable) - else -> return - } - } - } - if (isExhaustive) { - whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.Exhaustive) - } else { - whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.NotExhaustive(listOf())) - } - } - - // ------------------------ Enum exhaustiveness ------------------------ - - private fun checkEnumExhaustiveness(whenExpression: FirWhenExpression, enum: FirRegularClass, nullable: Boolean): Boolean { - val data = EnumExhaustivenessData( - enum.collectEnumEntries().map { it.symbol }.toMutableSet(), - !nullable - ) - for (branch in whenExpression.branches) { - branch.condition.accept(EnumExhaustivenessVisitor, data) - } - return data.containsNull && data.remainingEntries.isEmpty() - } - - private class EnumExhaustivenessData(val remainingEntries: MutableSet>, var containsNull: Boolean) - - private object EnumExhaustivenessVisitor : FirVisitor() { - override fun visitElement(element: FirElement, data: EnumExhaustivenessData) {} - - override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: EnumExhaustivenessData) { - if (equalityOperatorCall.operation.let { it == FirOperation.EQ || it == FirOperation.IDENTITY }) { - when (val argument = equalityOperatorCall.arguments[1]) { - is FirConstExpression<*> -> { - if (argument.value == null) { - data.containsNull = true - } - } - is FirQualifiedAccessExpression -> { - if (argument.typeRef.isNullableNothing) { - data.containsNull = true - return - } - val reference = argument.calleeReference as? FirResolvedNamedReference ?: return - val symbol = (reference.resolvedSymbol.fir as? FirEnumEntry)?.symbol ?: return - - data.remainingEntries.remove(symbol) - } - } - } - } - - override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: EnumExhaustivenessData) { - if (binaryLogicExpression.kind == LogicOperationKind.OR) { - binaryLogicExpression.acceptChildren(this, data) - } - } - } - - // ------------------------ Sealed class exhaustiveness ------------------------ - - private fun checkSealedClassExhaustiveness( - whenExpression: FirWhenExpression, - sealedClass: FirRegularClass, - nullable: Boolean - ): Boolean { - if (sealedClass.sealedInheritors.isNullOrEmpty()) return true - - val data = SealedExhaustivenessData(sealedClass, !nullable) - for (branch in whenExpression.branches) { - branch.condition.accept(SealedExhaustivenessVisitor, data) - } - return data.isExhaustive() - } - - private inner class SealedExhaustivenessData(regularClass: FirRegularClass, var containsNull: Boolean) { - val symbolProvider = bodyResolveComponents.symbolProvider - private val rootNode = SealedClassInheritors(regularClass.classId, regularClass.sealedInheritors.mapToSealedInheritors()) - - private fun List?.mapToSealedInheritors(): MutableSet? { - if (this.isNullOrEmpty()) return null - - return this.mapNotNull { - val inheritor = symbolProvider.getClassLikeSymbolByFqName(it)?.fir as? FirRegularClass ?: return@mapNotNull null - SealedClassInheritors(inheritor.classId, inheritor.sealedInheritors.mapToSealedInheritors()) - }.takeIf { it.isNotEmpty() }?.toMutableSet() - } - - fun removeInheritor(classId: ClassId) { - if (rootNode.classId == classId) { - rootNode.inheritors?.clear() + val subjectType = whenExpression.subjectVariable?.returnTypeRef?.coneType + ?: whenExpression.subject?.typeRef?.coneType + ?: run { + whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.NotExhaustive.NO_ELSE_BRANCH) return } - rootNode.removeInheritor(classId) - } + val session = bodyResolveComponents.session + val cleanSubjectType = subjectType.fullyExpandedType(session).lowerBoundIfFlexible() - fun isExhaustive() = containsNull && rootNode.isEmpty() - } - - private data class SealedClassInheritors(val classId: ClassId, val inheritors: MutableSet? = null) { - fun removeInheritor(classId: ClassId): Boolean { - return inheritors != null && (inheritors.removeIf { it.classId == classId } || inheritors.any { it.removeInheritor(classId) }) - } - - fun isEmpty(): Boolean { - return inheritors != null && inheritors.all { it.isEmpty() } - } - } - - private object SealedExhaustivenessVisitor : FirDefaultVisitor() { - override fun visitElement(element: FirElement, data: SealedExhaustivenessData) {} - - override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: SealedExhaustivenessData) { - if (typeOperatorCall.operation == FirOperation.IS) { - typeOperatorCall.conversionTypeRef.accept(this, data) + val checkers = buildList { + exhaustivenessCheckers.filterTo(this) { it.isApplicable(cleanSubjectType, session) } + if (isNotEmpty() && cleanSubjectType.isMarkedNullable) { + add(WhenOnNullableExhaustivenessChecker) } } - override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: SealedExhaustivenessData) { - if (equalityOperatorCall.operation.let { it == FirOperation.EQ || it == FirOperation.IDENTITY }) { - when (val argument = equalityOperatorCall.arguments[1]) { - is FirConstExpression<*> -> { - if (argument.value == null) { - data.containsNull = true - } - } - - is FirResolvedQualifier -> { - argument.typeRef.accept(this, data) - } - - is FirQualifiedAccessExpression -> { - if (argument.typeRef.isNullableNothing) { - data.containsNull = true - } - } - } - } + if (checkers.isEmpty()) { + whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.NotExhaustive.NO_ELSE_BRANCH) + return + } + val whenMissingCases = mutableListOf() + for (checker in checkers) { + checker.computeMissingCases(whenExpression, cleanSubjectType, session, whenMissingCases) + } + if (whenMissingCases.isEmpty() && whenExpression.branches.isEmpty()) { + whenMissingCases.add(WhenMissingCase.Unknown) } - override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: SealedExhaustivenessData) { - val lookupTag = (resolvedTypeRef.type as? ConeLookupTagBasedType)?.lookupTag ?: return - val symbol = data.symbolProvider.getSymbolByLookupTag(lookupTag) as? FirClassSymbol ?: return - data.removeInheritor(symbol.classId) + val status = if (whenMissingCases.isEmpty()) { + ExhaustivenessStatus.Exhaustive + } else { + ExhaustivenessStatus.NotExhaustive(whenMissingCases) + } + whenExpression.replaceExhaustivenessStatus(status) + } +} + +private sealed class WhenExhaustivenessChecker { + abstract fun isApplicable(subjectType: ConeKotlinType, session: FirSession): Boolean + abstract fun computeMissingCases( + whenExpression: FirWhenExpression, + subjectType: ConeKotlinType, + session: FirSession, + destination: MutableCollection + ) + + protected abstract class AbstractConditionChecker : FirVisitor() { + override fun visitElement(element: FirElement, data: D) {} + + override fun visitWhenExpression(whenExpression: FirWhenExpression, data: D) { + whenExpression.branches.forEach { it.accept(this, data) } } - override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: SealedExhaustivenessData) { - if (binaryLogicExpression.kind == LogicOperationKind.OR) { + override fun visitWhenBranch(whenBranch: FirWhenBranch, data: D) { + whenBranch.condition.accept(this, data) + } + + override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: D) { + if (binaryLogicExpression.kind == OR) { binaryLogicExpression.acceptChildren(this, data) } } } +} - // ------------------------ Boolean exhaustiveness ------------------------ - - private fun checkBooleanExhaustiveness(whenExpression: FirWhenExpression, nullable: Boolean): Boolean { - val flags = BooleanExhaustivenessFlags(!nullable) - for (branch in whenExpression.branches) { - branch.condition.accept(BooleanExhaustivenessVisitor, flags) - } - return flags.containsTrue && flags.containsFalse && flags.containsNull +private object WhenOnNullableExhaustivenessChecker : WhenExhaustivenessChecker() { + override fun isApplicable(subjectType: ConeKotlinType, session: FirSession): Boolean { + return subjectType.isNullable } - private class BooleanExhaustivenessFlags(var containsNull: Boolean) { + override fun computeMissingCases( + whenExpression: FirWhenExpression, + subjectType: ConeKotlinType, + session: FirSession, + destination: MutableCollection + ) { + val flags = Flags() + whenExpression.accept(ConditionChecker, flags) + if (!flags.containsNull) { + destination.add(WhenMissingCase.NullIsMissing) + } + } + + private class Flags { + var containsNull = false + } + + private object ConditionChecker : AbstractConditionChecker() { + override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Flags) { + val argument = equalityOperatorCall.arguments[1] + if (argument.typeRef.isNullableNothing) { + data.containsNull = true + } + } + + override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Flags) { + if (typeOperatorCall.conversionTypeRef.coneType.isNullable) { + data.containsNull = true + } + } + } +} + +private object WhenOnBooleanExhaustivenessChecker : WhenExhaustivenessChecker() { + override fun isApplicable(subjectType: ConeKotlinType, session: FirSession): Boolean { + return subjectType.classId == StandardClassIds.Boolean + } + + private class Flags { var containsTrue = false var containsFalse = false } - private object BooleanExhaustivenessVisitor : FirVisitor() { - override fun visitElement(element: FirElement, data: BooleanExhaustivenessFlags) {} + override fun computeMissingCases( + whenExpression: FirWhenExpression, + subjectType: ConeKotlinType, + session: FirSession, + destination: MutableCollection + ) { + val flags = Flags() + whenExpression.accept(ConditionChecker, flags) + if (!flags.containsFalse) { + destination.add(WhenMissingCase.BooleanIsMissing.False) + } + if (!flags.containsTrue) { + destination.add(WhenMissingCase.BooleanIsMissing.True) + } + } - override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: BooleanExhaustivenessFlags) { + private object ConditionChecker : AbstractConditionChecker() { + override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Flags) { if (equalityOperatorCall.operation.let { it == FirOperation.EQ || it == FirOperation.IDENTITY }) { val argument = equalityOperatorCall.arguments[1] if (argument is FirConstExpression<*>) { when (argument.value) { true -> data.containsTrue = true false -> data.containsFalse = true - null -> data.containsNull = true } } } } + } +} - override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: BooleanExhaustivenessFlags) { - if (binaryLogicExpression.kind == LogicOperationKind.OR) { - binaryLogicExpression.acceptChildren(this, data) - } +private object WhenOnEnumExhaustivenessChecker : WhenExhaustivenessChecker() { + override fun isApplicable(subjectType: ConeKotlinType, session: FirSession): Boolean { + val symbol = subjectType.toSymbol(session) as? FirRegularClassSymbol ?: return false + return symbol.fir.classKind == ClassKind.ENUM_CLASS + } + + override fun computeMissingCases( + whenExpression: FirWhenExpression, + subjectType: ConeKotlinType, + session: FirSession, + destination: MutableCollection + ) { + val enumClass = (subjectType.toSymbol(session) as FirRegularClassSymbol).fir + val allEntries = enumClass.declarations.mapNotNullTo(mutableSetOf()) { it as? FirEnumEntry } + val checkedEntries = mutableSetOf() + whenExpression.accept(ConditionChecker, checkedEntries) + val notCheckedEntries = allEntries - checkedEntries + notCheckedEntries.mapTo(destination) { WhenMissingCase.EnumCheckIsMissing(it.symbol.callableId) } + } + + private object ConditionChecker : AbstractConditionChecker>() { + override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: MutableSet) { + if (!equalityOperatorCall.operation.let { it == FirOperation.EQ || it == FirOperation.IDENTITY }) return + val argument = equalityOperatorCall.arguments[1] + val symbol = argument.toResolvedCallableReference()?.resolvedSymbol as? FirVariableSymbol<*> ?: return + val checkedEnumEntry = symbol.fir as? FirEnumEntry ?: return + data.add(checkedEnumEntry) + } + } +} + +private object WhenOnSealedClassExhaustivenessChecker : WhenExhaustivenessChecker() { + override fun isApplicable(subjectType: ConeKotlinType, session: FirSession): Boolean { + return (subjectType.toSymbol(session)?.fir as? FirRegularClass)?.modality == Modality.SEALED + } + + override fun computeMissingCases( + whenExpression: FirWhenExpression, + subjectType: ConeKotlinType, + session: FirSession, + destination: MutableCollection + ) { + val allSubclasses = subjectType.toSymbol(session)?.collectAllSubclasses(session) ?: return + val checkedSubclasses = mutableSetOf>() + whenExpression.accept(ConditionChecker, Flags(allSubclasses, checkedSubclasses, session)) + (allSubclasses - checkedSubclasses).mapNotNullTo(destination) { + when (it) { + is FirClassSymbol<*> -> WhenMissingCase.IsTypeCheckIsMissing(it.classId, it.fir.classKind.isSingleton) + is FirVariableSymbol<*> -> WhenMissingCase.EnumCheckIsMissing(it.callableId) + else -> null + } + } + } + + private class Flags( + val allSubclasses: Set>, + val checkedSubclasses: MutableSet>, + val session: FirSession + ) + + private object ConditionChecker : AbstractConditionChecker() { + override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Flags) { + val isNegated = when (equalityOperatorCall.operation) { + FirOperation.EQ, FirOperation.IDENTITY -> false + FirOperation.NOT_EQ, FirOperation.NOT_IDENTITY -> true + else -> return + } + + val symbol = when (val argument = equalityOperatorCall.arguments[1]) { + is FirResolvedQualifier -> { + val firClass = (argument.symbol as? FirRegularClassSymbol)?.fir + if (firClass?.classKind == ClassKind.OBJECT) { + firClass.symbol + } else { + firClass?.companionObject?.symbol + } + } + else -> { + argument.toResolvedCallableSymbol()?.takeIf { it.fir is FirEnumEntry } + } + } ?: return + processBranch(symbol, isNegated, data) + } + + override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Flags) { + val isNegated = when (typeOperatorCall.operation) { + FirOperation.IS -> false + FirOperation.NOT_IS -> true + else -> return + } + val symbol = typeOperatorCall.conversionTypeRef.coneType.fullyExpandedType(data.session).toSymbol(data.session) ?: return + processBranch(symbol, isNegated, data) + } + + private fun processBranch(symbolToCheck: AbstractFirBasedSymbol<*>, isNegated: Boolean, flags: Flags) { + val subclassesOfType = symbolToCheck.collectAllSubclasses(flags.session) + if (subclassesOfType.none { it in flags.allSubclasses }) { + return + } + val checkedSubclasses = if (isNegated) flags.allSubclasses - subclassesOfType else subclassesOfType + flags.checkedSubclasses.addAll(checkedSubclasses) + } + } + + + private fun AbstractFirBasedSymbol<*>.collectAllSubclasses(session: FirSession): Set> { + return mutableSetOf>().apply { collectAllSubclassesTo(this, session) } + } + + private fun AbstractFirBasedSymbol<*>.collectAllSubclassesTo(destination: MutableSet>, session: FirSession) { + if (this !is FirRegularClassSymbol) { + destination.add(this) + return + } + when { + fir.modality == Modality.SEALED -> fir.sealedInheritors?.forEach { + val symbol = session.symbolProvider.getClassLikeSymbolByFqName(it) as? FirRegularClassSymbol + symbol?.collectAllSubclassesTo(destination, session) + } + fir.classKind == ClassKind.ENUM_CLASS -> fir.collectEnumEntries().mapTo(destination) { it.symbol } + else -> destination.add(this) } } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt index 50966403df1..ddac6cf5b4f 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/ExhaustivenessStatus.kt @@ -5,19 +5,61 @@ package org.jetbrains.kotlin.fir.expressions +import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.name.ClassId sealed class ExhaustivenessStatus { object Exhaustive : ExhaustivenessStatus() - class NotExhaustive(val reasons: List) : ExhaustivenessStatus() + class NotExhaustive(val reasons: List) : ExhaustivenessStatus() { + companion object { + val NO_ELSE_BRANCH = NotExhaustive(listOf(WhenMissingCase.Unknown)) + } + } } -sealed class WhenMissingCase { - object Unknown : WhenMissingCase() - object NullIsMissing : WhenMissingCase() - class BooleanIsMissing(val value: Boolean) : WhenMissingCase() - class IsTypeCheckIsMissing(val classId: ClassId) : WhenMissingCase() - class EnumCheckIsMissing(val classId: ClassId) : WhenMissingCase() +sealed class WhenMissingCase() { + abstract val branchConditionText: String + + object Unknown : WhenMissingCase() { + override fun toString(): String = "unknown" + + override val branchConditionText: String = "else" + } + + object NullIsMissing : WhenMissingCase() { + override val branchConditionText: String = "null" + } + + sealed class BooleanIsMissing(val value: Boolean) : WhenMissingCase() { + object True : BooleanIsMissing(true) + object False : BooleanIsMissing(false) + + override val branchConditionText: String = value.toString() + } + + class IsTypeCheckIsMissing(val classId: ClassId, val isSingleton: Boolean) : WhenMissingCase() { + override val branchConditionText: String = run { + val fqName = classId.asSingleFqName().toString() + if (isSingleton) fqName else "is $fqName" + } + + override fun toString(): String { + val name = classId.shortClassName.identifier + return if (isSingleton) name else "is $name" + } + } + + class EnumCheckIsMissing(val callableId: CallableId) : WhenMissingCase() { + override val branchConditionText: String = callableId.asFqNameForDebugInfo().toString() + + override fun toString(): String { + return callableId.callableName.identifier + } + } + + override fun toString(): String { + return branchConditionText + } } val FirWhenExpression.isExhaustive: Boolean diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt index c393564b456..04b049c2dc3 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt @@ -18,6 +18,6 @@ fun test2(x: Stmt): String = } fun test3(x: Expr): String = - when (x) { + when (x) { is Stmt -> "stmt" } diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt deleted file mode 100644 index fab86d219d0..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt +++ /dev/null @@ -1,34 +0,0 @@ -sealed class Base { - sealed class A : Base() { - object A1 : A() - sealed class A2 : A() - } - sealed class B : Base() { - sealed class B1 : B() - object B2 : B() - } - - fun foo() = when (this) { - is A -> 1 - is B.B1 -> 2 - B.B2 -> 3 - // No else required - } - - fun bar() = when (this) { - is A -> 1 - is B.B1 -> 2 - } - - fun baz() = when (this) { - is A -> 1 - B.B2 -> 3 - // No else required (no possible B1 instances) - } - - fun negated() = when (this) { - !is A -> 1 - A.A1 -> 2 - is A.A2 -> 3 - } -} diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.kt index 292767ade22..598ce99c605 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class Base { sealed class A : Base() { object A1 : A() From d7e3e83251dfb9e8137a79794ce70567b3c4baa8 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Sat, 6 Feb 2021 12:48:46 +0300 Subject: [PATCH 056/153] [FIR] Update testdata of FIR spec tests --- .../p-1/neg/1.1.fir.kt | 19 ----- .../conditional-expressions/p-1/neg/1.1.kt | 1 + .../p-1/neg/1.2.fir.kt | 11 ++- .../p-1/neg/1.3.fir.kt | 25 ++++--- .../p-1/neg/2.1.fir.kt | 12 +++- .../p-2/neg/1.1.fir.kt | 16 ----- .../p-2/neg/1.1.kt | 1 + .../p-2/neg/1.2.fir.kt | 17 ----- .../p-2/neg/1.2.kt | 1 + .../p-2/neg/11.1.fir.kt | 19 ----- .../p-2/neg/11.1.kt | 1 + .../p-2/neg/11.2.fir.kt | 72 ------------------- .../p-2/neg/11.2.kt | 1 + .../p-2/neg/11.3.fir.kt | 37 ---------- .../p-2/neg/11.3.kt | 1 + .../p-2/neg/3.1.fir.kt | 36 ---------- .../p-2/neg/3.1.kt | 1 + .../p-2/neg/9.1.fir.kt | 33 +++++---- .../p-2/pos/11.1.fir.kt | 24 +++++++ .../p-2/pos/11.1.kt | 1 - .../p-2/pos/11.2.fir.kt | 9 +++ .../p-2/pos/3.1.fir.kt | 22 ++++++ .../p-2/pos/3.1.kt | 1 - .../when-expression/p-4/neg/1.1.fir.kt | 17 +++-- .../when-expression/p-4/pos/1.1.fir.kt | 13 +++- .../notLinked/coercion-to-unit/neg/1.fir.kt | 13 +++- .../diagnostics/notLinked/dfa/pos/62.fir.kt | 17 +++-- 27 files changed, 169 insertions(+), 252 deletions(-) delete mode 100644 compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.1.fir.kt delete mode 100644 compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.1.fir.kt delete mode 100644 compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.2.fir.kt delete mode 100644 compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.fir.kt delete mode 100644 compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.2.fir.kt delete mode 100644 compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.3.fir.kt delete mode 100644 compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.fir.kt create mode 100644 compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.fir.kt create mode 100644 compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.fir.kt diff --git a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.1.fir.kt deleted file mode 100644 index 7ddc8f0f5a1..00000000000 --- a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.1.fir.kt +++ /dev/null @@ -1,19 +0,0 @@ -// !LANGUAGE: +NewInference -// !DIAGNOSTICS: -IMPLICIT_CAST_TO_ANY -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION -// SKIP_TXT - -// TESTCASE NUMBER: 1 - -fun case1() { - val b = true - val a = if (b) { - "true" - } -} - -// TESTCASE NUMBER: 2 - -fun case2() { - val b = true - val a = if (b) "true" -} diff --git a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.1.kt b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.1.kt index d44f58871e0..6f05ffc27e6 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.1.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.1.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +NewInference // !DIAGNOSTICS: -IMPLICIT_CAST_TO_ANY -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION // SKIP_TXT diff --git a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.2.fir.kt index 775c449d4a2..e29d0112510 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.2.fir.kt @@ -2,6 +2,15 @@ // !DIAGNOSTICS: -IMPLICIT_CAST_TO_ANY -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION // SKIP_TXT +/* + * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) + * + * SPEC VERSION: 0.1-296 + * MAIN LINK: control--and-data-flow-analysis, control-flow-graph, expressions-1, conditional-expressions -> paragraph 1 -> sentence 1 + * NUMBER: 2 + * DESCRIPTION: check if-expressions must have both branches. + */ + // TESTCASE NUMBER: 1 fun case1() { @@ -9,7 +18,7 @@ fun case1() { val c = true val a = if (b) { "first true" - } else if (c) { + } else if (c) { "else if true" } } diff --git a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.3.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.3.fir.kt index 1767cf6d9e7..5f9a0c36a00 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/1.3.fir.kt @@ -2,6 +2,15 @@ // !DIAGNOSTICS: -UNREACHABLE_CODE -IMPLICIT_CAST_TO_ANY -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION // SKIP_TXT +/* + * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) + * + * SPEC VERSION: 0.1-296 + * MAIN LINK: control--and-data-flow-analysis, control-flow-graph, expressions-1, conditional-expressions -> paragraph 1 -> sentence 1 + * NUMBER: 3 + * DESCRIPTION: check if-expressions must have both branches. (attempt to pass Nothing to if-condition without 'else' key word) + */ + fun throwExc(b: Boolean): Boolean { if (b) throw Exception() else return false @@ -9,13 +18,13 @@ fun throwExc(b: Boolean): Boolean { // TESTCASE NUMBER: 1 fun case1() { - val x1 = if (throwExc(false)) true + val x1 = if (throwExc(false)) true } // TESTCASE NUMBER: 3 fun case3() { - val x1 = if (throwExc(true)) true + val x1 = if (throwExc(true)) true } /* @@ -24,18 +33,18 @@ fun case3() { * ISSUES: KT-35510 */ fun case4() { - val x1 = if (throw Exception()) true + val x1 = if (throw Exception()) true - val x2 = if (TODO()) true + val x2 = if (TODO()) true - val x0 = if (false) true else if (throw Exception()) ; + val x0 = if (false) true else if (throw Exception()) ; } // TESTCASE NUMBER: 5 fun case5() { var flag: Boolean? = null - val x1 = if (flag ?: throw Exception()) true + val x1 = if (flag ?: throw Exception()) true } /* @@ -44,7 +53,7 @@ fun case5() { * ISSUES: KT-35510 */ fun case6() { - val k1 = if(throw Exception()); + val k1 = if(throw Exception()); } /* @@ -62,7 +71,7 @@ fun case7(nothing: Nothing) { * ISSUES: KT-35510 */ fun case8(nothing: Nothing) { - val x1 = if (nothing) true + val x1 = if (nothing) true } /* diff --git a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/2.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/2.1.fir.kt index fd3905ad21e..86ea234ab6c 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/2.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/control--and-data-flow-analysis/control-flow-graph/expressions-1/conditional-expressions/p-1/neg/2.1.fir.kt @@ -2,6 +2,16 @@ // !DIAGNOSTICS: -UNUSED_VARIABLE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_PARAMETER -UNUSED_EXPRESSION // SKIP_TXT +/* + * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) + * + * SPEC VERSION: 0.1-296 + * MAIN LINK: control--and-data-flow-analysis, control-flow-graph, expressions-1, conditional-expressions -> paragraph 1 -> sentence 2 + * NUMBER: 1 + * DESCRIPTION: check any if-statement in kotlin may be trivially turned into such an expression by replacing the missing branch with a kotlin.Unit object expression. + * HELPERS: checkType + */ + // TESTCASE NUMBER: 1 fun case1() { @@ -9,7 +19,7 @@ fun case1() { if (!b) { println("this is statement") } - val statement = if (!b) { println("statement could not be assigned") } + val statement = if (!b) { println("statement could not be assigned") } } // TESTCASE NUMBER: 2 diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.1.fir.kt deleted file mode 100644 index 54f48e8883c..00000000000 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.1.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -// SKIP_TXT - -// TESTCASE NUMBER: 1 -fun case_1(value_1: Int): String = when { - value_1 == 1 -> "" - value_1 == 2 -> "" - value_1 == 3 -> "" -} - -// TESTCASE NUMBER: 2 -fun case_2(value_1: Int): String = when { - value_1 == 1 -> "" -} - -// TESTCASE NUMBER: 3 -fun case_3(): Int = when {} diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.1.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.1.kt index ca615536179..62f00d0c2c2 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.1.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.1.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // SKIP_TXT /* diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.2.fir.kt deleted file mode 100644 index bd125a9d679..00000000000 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.2.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_EXPRESSION -// SKIP_TXT - -// TESTCASE NUMBER: 1 -fun case_1(value_1: Int): String = when (value_1) { - 1 -> "" - 2 -> "" - 3 -> "" -} - -// TESTCASE NUMBER: 2 -fun case_2(value_1: Int): String = when (value_1) { - 1 -> "" -} - -// TESTCASE NUMBER: 3 -fun case_3(value_1: Int): Int = when (value_1) {} diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.2.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.2.kt index 6df980a3982..2621f903616 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.2.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/1.2.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_EXPRESSION // SKIP_TXT diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.fir.kt deleted file mode 100644 index eb07a21078b..00000000000 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.fir.kt +++ /dev/null @@ -1,19 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_EXPRESSION -// SKIP_TXT - - - -// TESTCASE NUMBER: 1 -fun case_1(value_1: Boolean?): String = when(value_1) { - true -> "" - false -> "" -} - -// TESTCASE NUMBER: 2 -fun case_2(value_1: Boolean?): String = when(value_1) { - true -> "" - null -> "" -} - -// TESTCASE NUMBER: 3 -fun case_3(value_1: Boolean?): Int = when(value_1) { } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.kt index 9e3a53b5d06..836b4f37b7d 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_EXPRESSION // SKIP_TXT diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.2.fir.kt deleted file mode 100644 index 5f3ce02603a..00000000000 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.2.fir.kt +++ /dev/null @@ -1,72 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_EXPRESSION -// SKIP_TXT - - -// TESTCASE NUMBER: 1 -fun case_1(value_1: SealedClass?): String = when(value_1) { - is SealedChild1 -> "" - is SealedChild2 -> "" - is SealedChild3 -> "" -} - -// TESTCASE NUMBER: 2 -fun case_2(value_1: SealedClassMixed?): String = when(value_1) { - is SealedMixedChild1 -> "" - is SealedMixedChild2 -> "" - SealedMixedChildObject1 -> "" - null -> "" -} - -// TESTCASE NUMBER: 3 -fun case_3(value_1: SealedClassMixed?): String = when(value_1) { - null, is SealedMixedChild1, is SealedMixedChild2, SealedMixedChildObject1 -> "" -} - -// TESTCASE NUMBER: 4 -fun case_4(value_1: SealedClassMixed?): String = when(value_1) { - is SealedMixedChild1 -> "" - is SealedMixedChild2 -> "" - is SealedMixedChild3 -> "" - SealedMixedChildObject1 -> "" - SealedMixedChildObject2 -> "" - SealedMixedChildObject3 -> "" -} - -// TESTCASE NUMBER: 5 -fun case_5(value_1: SealedClassMixed?): String = when(value_1) { - is SealedMixedChild1 -> "" - is SealedMixedChild2 -> "" - is SealedMixedChild3 -> "" -} - -// TESTCASE NUMBER: 6 -fun case_6(value_1: SealedClassMixed?): Int = when(value_1) {} - -// TESTCASE NUMBER: 7 -fun case_7(value_1: SealedClassMixed?): String = when(value_1) { - is SealedMixedChild1 -> "" - is SealedMixedChild2-> "" - is SealedMixedChild3 -> "" - null -> "" -} - -// TESTCASE NUMBER: 8 -fun case_8(value_1: SealedClassMixed?): String = when(value_1) { - SealedMixedChildObject1 -> "" -} - -/* - * TESTCASE NUMBER: 9 - * DISCUSSION: maybe make exhaustive without else? - */ -fun case_9(value_1: Any?): String = when (value_1) { - is Any -> "" - null -> "" -} - -/* - * TESTCASE NUMBER: 10 - * DISCUSSION - * ISSUES: KT-26044 - */ -fun case_10(value: SealedClassEmpty): String = when (value) {} diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.2.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.2.kt index 014eec0ea2a..270201e6b75 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.2.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.2.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_EXPRESSION // SKIP_TXT diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.3.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.3.fir.kt deleted file mode 100644 index e91e58f4ee1..00000000000 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.3.fir.kt +++ /dev/null @@ -1,37 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_EXPRESSION -// SKIP_TXT - - -// TESTCASE NUMBER: 1 -fun case_1(value_1: EnumClass?): String = when(value_1) { - EnumClass.EAST -> "" - EnumClass.SOUTH -> "" - EnumClass.NORTH -> "" - EnumClass.WEST -> "" -} - -// TESTCASE NUMBER: 2 -fun case_2(value_1: EnumClass?): String = when(value_1) { - EnumClass.EAST -> "" - EnumClass.SOUTH -> "" - EnumClass.NORTH -> "" - null -> "" -} - -// TESTCASE NUMBER: 3 -fun case_3(value_1: EnumClass?): String = when(value_1) { - EnumClass.EAST, null, EnumClass.SOUTH, EnumClass.NORTH -> "" -} - -// TESTCASE NUMBER: 4 -fun case_4(value_1: EnumClassSingle): Int = when(value_1) {} - -// TESTCASE NUMBER: 5 -fun case_5(value_1: EnumClassSingle?): String = when(value_1) { - EnumClassSingle.EVERYTHING -> "" -} - -// TESTCASE NUMBER: 6 -fun case_6(value_1: EnumClassSingle?): String = when(value_1) { - null -> "" -} diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.3.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.3.kt index 1a7f76a7371..69b5d521070 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.3.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.3.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_EXPRESSION // SKIP_TXT diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.fir.kt deleted file mode 100644 index b2120411a79..00000000000 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.fir.kt +++ /dev/null @@ -1,36 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_EXPRESSION -// SKIP_TXT - -// TESTCASE NUMBER: 1 -fun case_1(value_1: Boolean): String = when(value_1) { - true -> "" -} - -// TESTCASE NUMBER: 2 -fun case_2(value_1: Boolean): String = when(value_1) { - false -> "" -} - -// TESTCASE NUMBER: 3 -fun case_3(value_1: Boolean): Int = when(value_1) { } - -// TESTCASE NUMBER: 4 -fun case_4(value_1: Boolean): String = when { - value_1 == true -> "" - value_1 == false -> "" -} - -/* - * TESTCASE NUMBER: 5 - * DISCUSSION: maybe use const propagation here? - * ISSUES: KT-25265 - */ -fun case_5(value_1: Boolean): String { - val trueValue = true - val falseValue = false - - return when (value_1) { - trueValue -> "" - falseValue -> "" - } -} diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.kt index 31e7ae51243..ab7cdda9b7b 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_EXPRESSION // SKIP_TXT diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/9.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/9.1.fir.kt index 64a2e11d768..03a0b7bb732 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/9.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/9.1.fir.kt @@ -1,48 +1,57 @@ // !DIAGNOSTICS: -UNUSED_EXPRESSION // SKIP_TXT +/* + * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) + * + * SPEC VERSION: 0.1-435 + * MAIN LINK: expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 9 + * NUMBER: 1 + * DESCRIPTION: Non-exhaustive when using subclasses of the sealed class. + * HELPERS: sealedClasses + */ // TESTCASE NUMBER: 1 -fun case_1(value_1: SealedClass): String = when(value_1) { +fun case_1(value_1: SealedClass): String = when(value_1) { is SealedChild1 -> "" is SealedChild2 -> "" } // TESTCASE NUMBER: 2 -fun case_2(value_1: SealedClass): String = when(value_1) { +fun case_2(value_1: SealedClass): String = when(value_1) { is SealedChild1, is SealedChild2 -> "" } // TESTCASE NUMBER: 3 -fun case_3(value_1: SealedClassMixed): String = when(value_1) { +fun case_3(value_1: SealedClassMixed): String = when(value_1) { is SealedMixedChild1 -> "" is SealedMixedChild2 -> "" SealedMixedChildObject1 -> "" } // TESTCASE NUMBER: 4 -fun case_4(value_1: SealedClassMixed): String = when(value_1) { +fun case_4(value_1: SealedClassMixed): String = when(value_1) { SealedMixedChildObject1, is SealedMixedChild2, is SealedMixedChild1 -> "" } // TESTCASE NUMBER: 5 -fun case_5(value_1: SealedClassMixed): String = when(value_1) { +fun case_5(value_1: SealedClassMixed): String = when(value_1) { is SealedMixedChild1 -> "" is SealedMixedChild2 -> "" is SealedMixedChild3 -> "" } // TESTCASE NUMBER: 6 -fun case_6(value_1: SealedClassMixed): Int = when(value_1) { } +fun case_6(value_1: SealedClassMixed): Int = when(value_1) { } // TESTCASE NUMBER: 7 -fun case_7(value_1: SealedClassSingleWithObject): Int = when(value_1) { } +fun case_7(value_1: SealedClassSingleWithObject): Int = when(value_1) { } // TESTCASE NUMBER: 8 -fun case_8(value_1: SealedClassEmpty): String = when (value_1) { } +fun case_8(value_1: SealedClassEmpty): String = when (value_1) { } // TESTCASE NUMBER: 9 -fun case_9(value_1: Number): String = when (value_1) { +fun case_9(value_1: Number): String = when (value_1) { is Byte -> "" is Double -> "" is Float -> "" @@ -55,19 +64,19 @@ fun case_9(value_1: Number): String = when (value_1) { * TESTCASE NUMBER: 10 * DISCUSSION: maybe make exhaustive without else? */ -fun case_10(value_1: Any): String = when (value_1) { +fun case_10(value_1: Any): String = when (value_1) { is Any -> "" } // TESTCASE NUMBER: 11 -fun case_11(value_1: SealedClass): String = when { +fun case_11(value_1: SealedClass): String = when { value_1 is SealedChild1 -> "" value_1 is SealedChild2 -> "" value_1 is SealedChild3 -> "" } // TESTCASE NUMBER: 12 -fun case_12(value_1: SealedClassMixed): String = when(value_1) { +fun case_12(value_1: SealedClassMixed): String = when(value_1) { is SealedMixedChild1 -> "" is SealedMixedChild2 -> "" is SealedMixedChild3 -> "" diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.fir.kt new file mode 100644 index 00000000000..a6bbd1d1652 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.fir.kt @@ -0,0 +1,24 @@ +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) + * + * SPEC VERSION: 0.1-435 + * MAIN LINK: expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 11 + * NUMBER: 1 + * DESCRIPTION: Exhaustive when using nullable boolean values. + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Boolean?): String = when (value_1) { + true -> "" + false -> "" + null -> "" +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Boolean?): String = when (value_1) { + true && false && ((true || false)) || true && !!!false && !!!true -> "" + true && false && ((true || false)) || true && !!!false -> "" + null -> "" +} diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.kt index c27fb8f45f7..073abe3ea85 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // SKIP_TXT /* diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.2.fir.kt index a57e44c723c..5802adafd71 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.2.fir.kt @@ -1,5 +1,14 @@ // SKIP_TXT +/* + * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) + * + * SPEC VERSION: 0.1-435 + * MAIN LINK: expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 11 + * NUMBER: 2 + * DESCRIPTION: Exhaustive when using nullable enum values. + * HELPERS: enumClasses + */ // TESTCASE NUMBER: 1 fun case_1(value_1: EnumClass?): String = when (value_1) { diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.fir.kt new file mode 100644 index 00000000000..3c414d2fff5 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.fir.kt @@ -0,0 +1,22 @@ +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) + * + * SPEC VERSION: 0.1-100 + * MAIN LINK: expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 3 + * NUMBER: 1 + * DESCRIPTION: Exhaustive when using boolean values. + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Boolean): String = when (value_1) { + true -> "" + false -> "" +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Boolean): String = when (value_1) { + true && false && ((true || false)) || true && !!!false && !!!true -> "" + true && false && ((true || false)) || true && !!!false -> "" +} diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.kt index 33c447aaad3..41f07c616de 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // SKIP_TXT /* diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-4/neg/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-4/neg/1.1.fir.kt index df48db627e0..7b0a61a6302 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-4/neg/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-4/neg/1.1.fir.kt @@ -3,6 +3,15 @@ // SKIP_TXT // FULL_JDK +/* + * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) + * + * SPEC VERSION: 0.1-313 + * MAIN LINK: expressions, when-expression -> paragraph 4 -> sentence 1 + * NUMBER: 1 + * DESCRIPTION: it is possible to replace the else condition with an always-true condition + */ + // FILE: JavaEnum.java enum JavaEnum { @@ -15,7 +24,7 @@ enum JavaEnum { // TESTCASE NUMBER: 1 fun case1() { val z = JavaEnum.Val_1 - val when2 = when (z) { + val when2 = when (z) { JavaEnum.Val_1 -> { } JavaEnum.Val_1 -> { } } @@ -26,7 +35,7 @@ fun case1() { fun case2() { val b = false - val when2: Any = when (b) { + val when2: Any = when (b) { false -> { } false -> { } } @@ -36,7 +45,7 @@ fun case2() { fun case3() { val a = false - val when2: Any = when (a) { + val when2: Any = when (a) { true -> { } true -> { } } @@ -46,7 +55,7 @@ fun case3() { fun case4() { val x: SClass = SClass.B() - val when2 = when (x){ + val when2 = when (x){ is SClass.A ->{ } is SClass.B ->{ } is SClass.B ->{ } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-4/pos/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-4/pos/1.1.fir.kt index 814b0720ea6..db667a1f77b 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-4/pos/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-4/pos/1.1.fir.kt @@ -3,6 +3,15 @@ // SKIP_TXT // FULL_JDK +/* + * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) + * + * SPEC VERSION: 0.1-313 + * MAIN LINK: expressions, when-expression -> paragraph 4 -> sentence 1 + * NUMBER: 1 + * DESCRIPTION: it is possible to replace the else condition with an always-true condition + */ + // FILE: JavaEnum.java enum JavaEnum { @@ -42,11 +51,11 @@ fun case2() { else -> { } } - val when2: Any = when (b) { + val when2: Any = when (b) { false -> { } !false -> { } } - val when3: Any = when (b) { + val when3: Any = when (b) { false -> { } false -> { } !false -> { } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/coercion-to-unit/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/coercion-to-unit/neg/1.fir.kt index 1cbb749a12e..e6c61bbe2e1 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/coercion-to-unit/neg/1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/coercion-to-unit/neg/1.fir.kt @@ -1,11 +1,20 @@ +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: coercion-to-unit + * NUMBER: 1 + * DESCRIPTION: Coercion to Unit error diagnostics absence + * ISSUES: KT-38490 + */ + // TESTCASE NUMBER: 1 val y0 = when (2) { - else -> if (true) {""} + else -> if (true) {""} } val w:Any = TODO() val y1 = when (2) { - else -> if (true) {""} // false ok with coercion to Unit + else -> if (true) {""} // false ok with coercion to Unit } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/62.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/62.fir.kt index 52460da9fda..aa7e83aa357 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/62.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/62.fir.kt @@ -2,6 +2,15 @@ // !DIAGNOSTICS: -UNUSED_EXPRESSION -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_VALUE -VARIABLE_WITH_REDUNDANT_INITIALIZER // SKIP_TXT +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: dfa + * NUMBER: 62 + * DESCRIPTION: Raw data flow analysis test + * HELPERS: classes, objects, typealiases, functions, enumClasses, interfaces, sealedClasses + */ + /* * TESTCASE NUMBER: 1 * UNEXPECTED BEHAVIOUR @@ -145,7 +154,7 @@ fun case_10(x: Any): String { */ fun case_11(x: Any?): String? { if (x is Nothing?) { - return when(x) { + return when(x) { null -> null } } @@ -159,7 +168,7 @@ fun case_11(x: Any?): String? { */ fun case_12(x: Any?): String? { if (x == null) { - return when(x) { + return when(x) { null -> null } } @@ -173,7 +182,7 @@ fun case_12(x: Any?): String? { */ fun case_13(x: Any?): String? { if (x === null) { - return when(x) { + return when(x) { null -> null } } @@ -187,7 +196,7 @@ fun case_13(x: Any?): String? { */ fun case_14(x: Any?): String? { x as Nothing? - return when(x) { + return when(x) { null -> null } } From e7fdc18ced4f1155ec4635bf05844c270e029f42 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Sat, 6 Feb 2021 12:52:54 +0300 Subject: [PATCH 057/153] [FIR] Fix `[JSP] Fast FIR tests` run configuration --- gradle/jps.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/jps.gradle.kts b/gradle/jps.gradle.kts index 07494f9c62e..463b2afb0eb 100644 --- a/gradle/jps.gradle.kts +++ b/gradle/jps.gradle.kts @@ -76,7 +76,7 @@ fun setupFirRunConfiguration() { | |