diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbol.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbol.kt index 70c9da05b79..8fc69b861d5 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbol.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbol.kt @@ -62,6 +62,7 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori FirDeclarationOrigin.Enhancement -> KtSymbolOrigin.JAVA FirDeclarationOrigin.IntersectionOverride -> KtSymbolOrigin.INTERSECTION_OVERRIDE FirDeclarationOrigin.Delegated -> KtSymbolOrigin.DELEGATED + FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk -> KtSymbolOrigin.LIBRARY is FirDeclarationOrigin.Synthetic -> { when { source?.kind == KtFakeSourceElementKind.DataClassGeneratedMembers -> KtSymbolOrigin.SOURCE_MEMBER_GENERATED diff --git a/analysis/analysis-api/testData/components/scopeProvider/memberScope/MutableList.pretty.txt b/analysis/analysis-api/testData/components/scopeProvider/memberScope/MutableList.pretty.txt index 5c41d1473c8..1003cf4f9f5 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/memberScope/MutableList.pretty.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/memberScope/MutableList.pretty.txt @@ -45,3 +45,7 @@ open operator fun equals(other: kotlin.Any?): kotlin.Boolean open fun hashCode(): kotlin.Int open fun toString(): kotlin.String + +fun getFirst(): E + +fun getLast(): E \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/scopeProvider/memberScope/MutableList.txt b/analysis/analysis-api/testData/components/scopeProvider/memberScope/MutableList.txt index ad7fb7fc48f..1f5ed2647d7 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/memberScope/MutableList.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/memberScope/MutableList.txt @@ -1546,4 +1546,86 @@ KtFunctionSymbol: getContainingFileSymbol: null getContainingJvmClassName: kotlin.Any getContainingModule: KtBinaryModule "Builtins for JVM (1.8)" + deprecationStatus: null + +KtFunctionSymbol: + annotationsList: [] + callableIdIfNonLocal: kotlin/collections/MutableList.getFirst + contextReceivers: [] + contractEffects: [] + hasStableParameterNames: true + isActual: false + isBuiltinFunctionInvoke: false + isExpect: false + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: OPEN + name: getFirst + origin: SUBSTITUTION_OVERRIDE + receiverParameter: null + returnType: KtTypeParameterType: + annotationsList: [] + type: E + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [] + visibility: Public + getDispatchReceiver(): KtUsualClassType: + annotationsList: [] + ownTypeArguments: [ + KtTypeParameterType: + annotationsList: [] + type: E + ] + type: kotlin/collections/MutableList + getContainingFileSymbol: null + getContainingJvmClassName: kotlin.collections.MutableList + getContainingModule: KtBinaryModule "Builtins for JVM (1.8)" + deprecationStatus: null + +KtFunctionSymbol: + annotationsList: [] + callableIdIfNonLocal: kotlin/collections/MutableList.getLast + contextReceivers: [] + contractEffects: [] + hasStableParameterNames: true + isActual: false + isBuiltinFunctionInvoke: false + isExpect: false + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: OPEN + name: getLast + origin: SUBSTITUTION_OVERRIDE + receiverParameter: null + returnType: KtTypeParameterType: + annotationsList: [] + type: E + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [] + visibility: Public + getDispatchReceiver(): KtUsualClassType: + annotationsList: [] + ownTypeArguments: [ + KtTypeParameterType: + annotationsList: [] + type: E + ] + type: kotlin/collections/MutableList + getContainingFileSymbol: null + getContainingJvmClassName: kotlin.collections.MutableList + getContainingModule: KtBinaryModule "Builtins for JVM (1.8)" deprecationStatus: null \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/scopeProvider/typeScope/intList.pretty.txt b/analysis/analysis-api/testData/components/scopeProvider/typeScope/intList.pretty.txt index e26fc12d91b..fe821cb897a 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/typeScope/intList.pretty.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/typeScope/intList.pretty.txt @@ -13,6 +13,8 @@ val size: kotlin.Int fun equals(other: kotlin.Any?): kotlin.Boolean fun hashCode(): kotlin.Int fun toString(): kotlin.String +fun getFirst(): kotlin.Int +fun getLast(): kotlin.Int Declaration Scope: @@ -30,3 +32,6 @@ val size: kotlin.Int fun equals(other: kotlin.Any?): kotlin.Boolean fun hashCode(): kotlin.Int fun toString(): kotlin.String +fun getFirst(): E +fun getLast(): E + diff --git a/analysis/analysis-api/testData/components/scopeProvider/typeScope/intList.txt b/analysis/analysis-api/testData/components/scopeProvider/typeScope/intList.txt index 82e53f1af38..0d138f2a155 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/typeScope/intList.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/typeScope/intList.txt @@ -148,6 +148,18 @@ KtFunctionLikeSignature: symbol = kotlin/Any.toString(: kotlin.Any): kotlin.String valueParameters = [] callableIdIfNonLocal = kotlin/Any.toString +KtFunctionLikeSignature: + receiverType = null + returnType = kotlin.Int + symbol = kotlin/collections/List.getFirst(: kotlin.collections.List): E + valueParameters = [] + callableIdIfNonLocal = kotlin/collections/List.getFirst +KtFunctionLikeSignature: + receiverType = null + returnType = kotlin.Int + symbol = kotlin/collections/List.getLast(: kotlin.collections.List): E + valueParameters = [] + callableIdIfNonLocal = kotlin/collections/List.getLast Declaration Scope: @@ -798,4 +810,60 @@ KtFunctionSymbol: typeParameters: [] valueParameters: [] visibility: Public +KtFunctionSymbol: + annotationsList: [] + callableIdIfNonLocal: kotlin/collections/List.getFirst + contextReceivers: [] + contractEffects: [] + hasStableParameterNames: true + isActual: false + isBuiltinFunctionInvoke: false + isExpect: false + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: OPEN + name: getFirst + origin: LIBRARY + receiverParameter: null + returnType: KtTypeParameterType: + annotationsList: [] + type: E + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [] + visibility: Public +KtFunctionSymbol: + annotationsList: [] + callableIdIfNonLocal: kotlin/collections/List.getLast + contextReceivers: [] + contractEffects: [] + hasStableParameterNames: true + isActual: false + isBuiltinFunctionInvoke: false + isExpect: false + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: OPEN + name: getLast + origin: LIBRARY + receiverParameter: null + returnType: KtTypeParameterType: + annotationsList: [] + type: E + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [] + visibility: Public diff --git a/analysis/analysis-api/testData/components/scopeProvider/typeScope/typeParamList.pretty.txt b/analysis/analysis-api/testData/components/scopeProvider/typeScope/typeParamList.pretty.txt index d2fe633c0e2..07be74a1a59 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/typeScope/typeParamList.pretty.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/typeScope/typeParamList.pretty.txt @@ -13,6 +13,8 @@ val size: kotlin.Int fun equals(other: kotlin.Any?): kotlin.Boolean fun hashCode(): kotlin.Int fun toString(): kotlin.String +fun getFirst(): AAA +fun getLast(): AAA Declaration Scope: @@ -30,3 +32,6 @@ val size: kotlin.Int fun equals(other: kotlin.Any?): kotlin.Boolean fun hashCode(): kotlin.Int fun toString(): kotlin.String +fun getFirst(): E +fun getLast(): E + diff --git a/analysis/analysis-api/testData/components/scopeProvider/typeScope/typeParamList.txt b/analysis/analysis-api/testData/components/scopeProvider/typeScope/typeParamList.txt index b6b7d150174..e6588691676 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/typeScope/typeParamList.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/typeScope/typeParamList.txt @@ -148,6 +148,18 @@ KtFunctionLikeSignature: symbol = kotlin/Any.toString(: kotlin.Any): kotlin.String valueParameters = [] callableIdIfNonLocal = kotlin/Any.toString +KtFunctionLikeSignature: + receiverType = null + returnType = AAA + symbol = kotlin/collections/List.getFirst(: kotlin.collections.List): E + valueParameters = [] + callableIdIfNonLocal = kotlin/collections/List.getFirst +KtFunctionLikeSignature: + receiverType = null + returnType = AAA + symbol = kotlin/collections/List.getLast(: kotlin.collections.List): E + valueParameters = [] + callableIdIfNonLocal = kotlin/collections/List.getLast Declaration Scope: @@ -798,4 +810,60 @@ KtFunctionSymbol: typeParameters: [] valueParameters: [] visibility: Public +KtFunctionSymbol: + annotationsList: [] + callableIdIfNonLocal: kotlin/collections/List.getFirst + contextReceivers: [] + contractEffects: [] + hasStableParameterNames: true + isActual: false + isBuiltinFunctionInvoke: false + isExpect: false + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: OPEN + name: getFirst + origin: LIBRARY + receiverParameter: null + returnType: KtTypeParameterType: + annotationsList: [] + type: E + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [] + visibility: Public +KtFunctionSymbol: + annotationsList: [] + callableIdIfNonLocal: kotlin/collections/List.getLast + contextReceivers: [] + contractEffects: [] + hasStableParameterNames: true + isActual: false + isBuiltinFunctionInvoke: false + isExpect: false + isExtension: false + isExternal: false + isInfix: false + isInline: false + isOperator: false + isOverride: false + isStatic: false + isSuspend: false + modality: OPEN + name: getLast + origin: LIBRARY + receiverParameter: null + returnType: KtTypeParameterType: + annotationsList: [] + type: E + symbolKind: CLASS_MEMBER + typeParameters: [] + valueParameters: [] + visibility: Public diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 5387a07f600..8a019d96126 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -38708,6 +38708,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.+)\\.(kt|kts)$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("newListMethods.kt") + public void testNewListMethods() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index a0ac003eb11..a4a0d9938b9 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -38708,6 +38708,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.+)\\.(kt|kts)$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("newListMethods.kt") + public void testNewListMethods() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 775d3c7102e..6dacd20ea3e 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -36334,6 +36334,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("newListMethods.kt") + public void testNewListMethods() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 8b73d43cc4a..8ae29cfac24 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -36460,6 +36460,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform"); } + @Test + @TestMetadata("newListMethods.kt") + public void testNewListMethods() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/FirJvmOverridesBackwardCompatibilityHelper.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/FirJvmOverridesBackwardCompatibilityHelper.kt index 33882aed078..7d7fa6ba9da 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/FirJvmOverridesBackwardCompatibilityHelper.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/FirJvmOverridesBackwardCompatibilityHelper.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.jvm import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper import org.jetbrains.kotlin.fir.containingClassLookupTag +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol @@ -19,6 +20,8 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol */ object FirJvmOverridesBackwardCompatibilityHelper : FirOverridesBackwardCompatibilityHelper() { override fun additionalCheck(member: FirCallableSymbol<*>): Boolean? { + if (member.origin == FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk) return true + if (!member.isJavaOrEnhancement) return false val containingClassName = member.containingClassLookupTag()?.classId?.asSingleFqName()?.toUnsafe() ?: return false // If the super class is mapped to a Kotlin built-in class, then we don't require `override` keyword. 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 48d1bebfb1a..8bcfc88c3fd 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 @@ -314,6 +314,7 @@ class FakeOverrideGenerator( val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S if (!session.visibilityChecker.isVisibleForOverriding(klass.moduleData, klass.symbol, baseSymbol.fir)) return + if (originalDeclaration.originalOrSelf().origin == FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk) return val (fakeOverrideFirDeclaration, baseFirSymbolsForFakeOverride) = when { originalSymbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) -> { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt index aa613ec2fd6..93fed22c6fd 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -229,6 +229,7 @@ class Fir2IrLazyClass( } private fun shouldBuildStub(fir: FirDeclaration): Boolean { + if (fir is FirCallableDeclaration && fir.originalOrSelf().origin == FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk) return false if (fir !is FirMemberDeclaration) return true return when { fir is FirConstructor -> isObject || isEnumClass || !Visibilities.isPrivate(fir.visibility) // This special case seams to be not needed anymore - KT-65172 diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/FirJvmDelegatedMembersFilter.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/FirJvmDelegatedMembersFilter.kt index 26067f1fba9..c4b67980b1a 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/FirJvmDelegatedMembersFilter.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/FirJvmDelegatedMembersFilter.kt @@ -28,7 +28,7 @@ class FirJvmDelegatedMembersFilter(private val session: FirSession) : FirDelegat override fun shouldNotGenerateDelegatedMember(memberSymbolFromSuperInterface: FirCallableSymbol<*>): Boolean { val original = memberSymbolFromSuperInterface.unwrapFakeOverrides() - return original.isNonAbstractJavaMethod() || original.hasJvmDefaultAnnotation() || original.isBuiltInMemberMappedToJavaDefault() + return original.isNonAbstractJavaMethod() || original.hasJvmDefaultAnnotation() || original.isBuiltInMemberMappedToJavaDefault() || original.origin == FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk } // If java interface method is not abstract, then it's a default method. diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt index 783aa963981..f87806fff37 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt @@ -7,11 +7,17 @@ package org.jetbrains.kotlin.fir.scopes.jvm import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsSignatures +import org.jetbrains.kotlin.descriptors.EffectiveVisibility +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.caches.* import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction +import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.utils.classId import org.jetbrains.kotlin.fir.declarations.utils.isFinal +import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.isRealOwnerOf import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes @@ -26,6 +32,8 @@ import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.ConeErrorType +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible @@ -36,6 +44,7 @@ import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.StandardClassIds /** * @param firKotlinClass Kotlin version of built-in class mapped to some JDK class (e.g. kotlin.collections.List) @@ -75,8 +84,10 @@ class JvmMappedScope( } } + private val isList: Boolean = firKotlinClass.classId == StandardClassIds.List + // It's ok to have a super set of actually available member names - private val myCallableNames by lazy { + private val myCallableNames: Set by lazy { if (firKotlinClass.isFinal) { // For final classes we don't need to load HIDDEN members at all because they might not be overridden val signaturePrefix = firJavaClass.symbol.classId.toString() @@ -91,6 +102,13 @@ class JvmMappedScope( declaredMemberScope.getCallableNames() + names } else { declaredMemberScope.getCallableNames() + javaMappedClassUseSiteScope.getCallableNames() + }.let { + // If getFirst/getLast don't exist, we need to add them so that we can mark overrides as deprecated (KT-65440) + if (isList && (GET_FIRST_NAME !in it || GET_LAST_NAME !in it)) { + it + listOf(GET_FIRST_NAME, GET_LAST_NAME) + } else { + it + } } } @@ -112,6 +130,8 @@ class JvmMappedScope( } } + var needsHiddenFake = isList && (name == GET_FIRST_NAME || name == GET_LAST_NAME) + javaMappedClassUseSiteScope.processFunctionsByName(name) processor@{ symbol -> if (!symbol.isDeclaredInMappedJavaClass() || !(symbol.fir.status as FirResolvedDeclarationStatus).visibility.isPublicAPI) { return@processor @@ -137,8 +157,46 @@ class JvmMappedScope( if ((jdkMemberStatus == JDKMemberStatus.HIDDEN || jdkMemberStatus == JDKMemberStatus.HIDDEN_IN_DECLARING_CLASS_ONLY) && firKotlinClass.isFinal) return@processor val newSymbol = mappedSymbolCache.mappedFunctions.getValue(symbol, this to jdkMemberStatus) + + if (needsHiddenFake && + allJavaMappedSuperClassIds.any { + SignatureBuildingComponents.signature(it, jvmDescriptor) in JvmBuiltInsSignatures.DEPRECATED_LIST_METHODS + } + ) { + needsHiddenFake = false + } + processor(newSymbol) } + + if (needsHiddenFake) { + // We're in JDK < 21, i.e., getFirst/getLast don't exist in the List interface yet. + // We create a fake version of them for the sole purpose of reporting deprecations on to-become-overrides like in LinkedList. + // This is because we want to rename these two methods in the future, + // and we want to warn users of older JDKs of a potential breaking change caused by upgrading to JDK >= 21. + // See KT-65440. + val fakeSymbol = mappedSymbolCache.hiddenFakeFunctions.getValue(name, this) + processor(fakeSymbol) + } + } + + private fun createHiddenFakeFunction(name: Name): FirNamedFunctionSymbol { + return buildSimpleFunction { + moduleData = firKotlinClass.moduleData + origin = FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk + status = FirResolvedDeclarationStatusImpl(Visibilities.Public, Modality.OPEN, EffectiveVisibility.Public) + returnTypeRef = buildResolvedTypeRef { + type = firKotlinClass.typeParameters.firstOrNull() + ?.let { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), isNullable = false) } + ?: ConeErrorType(ConeSimpleDiagnostic("No type parameter found on '${firKotlinClass.classKind}'")) + } + this.name = name + dispatchReceiverType = firKotlinClass.defaultType() + symbol = FirNamedFunctionSymbol(CallableId(firKotlinClass.classId, name)) + resolvePhase = FirResolvePhase.BODY_RESOLVE + }.apply { + isHiddenEverywhereBesideSuperCalls = HiddenEverywhereBesideSuperCallsStatus.HIDDEN_FAKE + }.symbol } private fun isOverrideOfKotlinDeclaredFunction(symbol: FirNamedFunctionSymbol) = @@ -335,6 +393,11 @@ class JvmMappedScope( scope.createMappedFunction(symbol, jdkMemberStatus) } + val hiddenFakeFunctions: FirCache = + cachesFactory.createCache { name, scope -> + scope.createHiddenFakeFunction(name) + } + val mappedConstructors: FirCache = cachesFactory.createCache { symbol, scope -> scope.createMappedConstructor(symbol) @@ -357,6 +420,9 @@ class JvmMappedScope( }, session ) + + private val GET_FIRST_NAME = Name.identifier("getFirst") + private val GET_LAST_NAME = Name.identifier("getLast") } override fun toString(): String { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/deprecationUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/deprecationUtils.kt index 2c31d76338b..ff107dd9ceb 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/deprecationUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/deprecationUtils.kt @@ -331,7 +331,7 @@ var FirCallableDeclaration.isHiddenEverywhereBesideSuperCalls: HiddenEverywhereB ) enum class HiddenEverywhereBesideSuperCallsStatus { - HIDDEN, HIDDEN_IN_DECLARING_CLASS_ONLY + HIDDEN, HIDDEN_IN_DECLARING_CLASS_ONLY, HIDDEN_FAKE, } private object IsHiddenToOvercomeSignatureClash : FirDeclarationDataKey() @@ -360,5 +360,7 @@ fun FirCallableSymbol<*>.isHidden(isSuperCall: Boolean, isOverridden: Boolean): // we report a deprecation warning on super calls because we might want to rename the method in the future // (getFirst -> first). HiddenEverywhereBesideSuperCallsStatus.HIDDEN_IN_DECLARING_CLASS_ONLY -> if (isSuperCall || isOverridden) CallToPotentiallyHiddenSymbolResult.VisibleWithDeprecation else CallToPotentiallyHiddenSymbolResult.Hidden + // HIDDEN_FAKE is always hidden (even for super calls), unless overridden. + HiddenEverywhereBesideSuperCallsStatus.HIDDEN_FAKE -> if (isOverridden) CallToPotentiallyHiddenSymbolResult.VisibleWithDeprecation else CallToPotentiallyHiddenSymbolResult.Hidden } } \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt index 6ce4c311772..777a82931d4 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt @@ -35,6 +35,7 @@ sealed class FirDeclarationOrigin( object FakeFunction : Synthetic() object ForwardDeclaration : Synthetic() object ScriptTopLevelDestructuringDeclarationContainer : Synthetic() + object FakeHiddenInPreparationForNewJdk : Synthetic() } object DynamicScope : FirDeclarationOrigin() object SamConstructor : FirDeclarationOrigin() diff --git a/compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.fir.kt b/compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.fir.kt new file mode 100644 index 00000000000..0e93c6222e7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.fir.kt @@ -0,0 +1,29 @@ +import java.util.LinkedList + +class A : ArrayList() { + fun getFirst(): T = super.getFirst() + fun getLast(): T = super.getLast() +} + +fun foo(x: List, y: LinkedList, z: A) { + x.getFirst() + x.first + x.first() // stdlib extension on List + x.getLast() + x.last + x.last() + + y.getFirst() + y.first + y.first() + y.getLast() + y.last + y.last() + + z.getFirst() + z.first + z.first() + z.getLast() + z.last + z.last() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt b/compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt new file mode 100644 index 00000000000..6a14c1b95af --- /dev/null +++ b/compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt @@ -0,0 +1,29 @@ +import java.util.LinkedList + +class A : ArrayList() { + fun getFirst(): T = super.getFirst() + fun getLast(): T = super.getLast() +} + +fun foo(x: List, y: LinkedList, z: A) { + x.getFirst() + x.first + x.first() // stdlib extension on List + x.getLast() + x.last + x.last() + + y.getFirst() + y.first + y.first() + y.getLast() + y.last + y.last() + + z.getFirst() + z.first + z.first() + z.getLast() + z.last + z.last() +} 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 ce44530c2d2..f6ed928212b 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 @@ -38708,6 +38708,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("newListMethods.kt") + public void testNewListMethods() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord") @TestDataPath("$PROJECT_ROOT") diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InlinerCycleReporter.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InlinerCycleReporter.kt index b44fdf15afd..1f4d0de8c57 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InlinerCycleReporter.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InlinerCycleReporter.kt @@ -83,6 +83,7 @@ class InlinerCycleReporter( } finally { if (!inlineCallInfos.isEmpty()) { + @Suppress("DEPRECATION") // KT-65247 if (inlineCallInfos.last.call == call) { inlineCallInfos.removeLast() }