[FIR][FE 1.0] KT-47933: Warn about redundant @Repeatable

Merge-request: KT-MR-7318
Merged-by: Nikolay Lunyak <Nikolay.Lunyak@jetbrains.com>
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt
index 140ac09..6c0567b 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt
@@ -6,7 +6,7 @@
 package org.jetbrains.kotlin.analysis.api.fir
 
 import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication
-import org.jetbrains.kotlin.analysis.api.fir.annotations.fullyExpandedClassId
+import org.jetbrains.kotlin.fir.declarations.fullyExpandedClassId
 import org.jetbrains.kotlin.analysis.api.fir.annotations.mapAnnotationParameters
 import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
 import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForDeclaration.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForDeclaration.kt
index 04383e8..007a4e0 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForDeclaration.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForDeclaration.kt
@@ -12,6 +12,7 @@
 import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
 import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
 import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.declarations.fullyExpandedClassId
 import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
 import org.jetbrains.kotlin.name.ClassId
 
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt
index c8cc8a7..edca47c 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/KtFirAnnotationListForType.kt
@@ -12,6 +12,7 @@
 import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
 import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
 import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.declarations.fullyExpandedClassId
 import org.jetbrains.kotlin.fir.types.ConeKotlinType
 import org.jetbrains.kotlin.fir.types.customAnnotations
 import org.jetbrains.kotlin.name.ClassId
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt
index 98cc0d8..b489a52 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt
@@ -90,6 +90,3 @@
 
     return resultMap
 }
-
-internal fun FirAnnotation.fullyExpandedClassId(useSiteSession: FirSession): ClassId? =
-    coneClassLikeType?.fullyExpandedType(useSiteSession)?.classId
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
index 725f6a7..5a6eecf 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
@@ -4178,6 +4178,14 @@
             token,
         )
     }
+    add(FirJvmErrors.REDUNDANT_REPEATABLE_ANNOTATION) { firDiagnostic ->
+        RedundantRepeatableAnnotationImpl(
+            firDiagnostic.a,
+            firDiagnostic.b,
+            firDiagnostic as KtPsiDiagnostic,
+            token,
+        )
+    }
     add(FirJvmErrors.LOCAL_JVM_RECORD) { firDiagnostic ->
         LocalJvmRecordImpl(
             firDiagnostic as KtPsiDiagnostic,
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
index 4d256c0..63ccb78 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
@@ -2908,6 +2908,12 @@
         override val diagnosticClass get() = PositionedValueArgumentForJavaAnnotation::class
     }
 
+    abstract class RedundantRepeatableAnnotation : KtFirDiagnostic<KtAnnotationEntry>() {
+        override val diagnosticClass get() = RedundantRepeatableAnnotation::class
+        abstract val kotlinRepeatable: FqName
+        abstract val javaRepeatable: FqName
+    }
+
     abstract class LocalJvmRecord : KtFirDiagnostic<PsiElement>() {
         override val diagnosticClass get() = LocalJvmRecord::class
     }
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
index c5cbcf5..62fcd7f 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
@@ -3514,6 +3514,13 @@
     override val token: KtLifetimeToken,
 ) : KtFirDiagnostic.PositionedValueArgumentForJavaAnnotation(), KtAbstractFirDiagnostic<KtExpression>
 
+internal class RedundantRepeatableAnnotationImpl(
+    override val kotlinRepeatable: FqName,
+    override val javaRepeatable: FqName,
+    override val firDiagnostic: KtPsiDiagnostic,
+    override val token: KtLifetimeToken,
+) : KtFirDiagnostic.RedundantRepeatableAnnotation(), KtAbstractFirDiagnostic<KtAnnotationEntry>
+
 internal class LocalJvmRecordImpl(
     override val firDiagnostic: KtPsiDiagnostic,
     override val token: KtLifetimeToken,
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
index 6395553..b3a70e2 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java
@@ -34867,6 +34867,12 @@
             }
 
             @Test
+            @TestMetadata("multipleRepeatables.kt")
+            public void testMultipleRepeatables() throws Exception {
+                runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.kt");
+            }
+
+            @Test
             @TestMetadata("qualifiedCallValue.kt")
             public void testQualifiedCallValue() throws Exception {
                 runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/qualifiedCallValue.kt");
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 44194f4..d3bc514 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
@@ -34867,6 +34867,12 @@
             }
 
             @Test
+            @TestMetadata("multipleRepeatables.kt")
+            public void testMultipleRepeatables() throws Exception {
+                runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.kt");
+            }
+
+            @Test
             @TestMetadata("qualifiedCallValue.kt")
             public void testQualifiedCallValue() throws Exception {
                 runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/qualifiedCallValue.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
index f97e0af..2409ee2 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java
@@ -34867,6 +34867,12 @@
             }
 
             @Test
+            @TestMetadata("multipleRepeatables.kt")
+            public void testMultipleRepeatables() throws Exception {
+                runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.kt");
+            }
+
+            @Test
             @TestMetadata("qualifiedCallValue.kt")
             public void testQualifiedCallValue() throws Exception {
                 runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/qualifiedCallValue.kt");
diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt
index 1bc6025..0f5b94c 100644
--- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt
+++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJvmDiagnosticsList.kt
@@ -79,6 +79,11 @@
         val JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_FILES_WITH_CLASSES by error<KtAnnotationEntry>()
 
         val POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION by error<KtExpression>()
+
+        val REDUNDANT_REPEATABLE_ANNOTATION by warning<KtAnnotationEntry> {
+            parameter<FqName>("kotlinRepeatable")
+            parameter<FqName>("javaRepeatable")
+        }
     }
 
     val SUPER by object : DiagnosticGroup("Super") {
diff --git a/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt b/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt
index a0fa674..361bfb6 100644
--- a/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt
+++ b/compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt
@@ -71,6 +71,7 @@
     val JVM_PACKAGE_NAME_MUST_BE_VALID_NAME by error0<KtAnnotationEntry>()
     val JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_FILES_WITH_CLASSES by error0<KtAnnotationEntry>()
     val POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION by error0<KtExpression>()
+    val REDUNDANT_REPEATABLE_ANNOTATION by warning2<KtAnnotationEntry, FqName, FqName>()
 
     // Super
     val SUPER_CALL_WITH_DEFAULT_PARAMETERS by error1<PsiElement, String>()
diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt
index 0b102e9..1b7da98 100644
--- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt
+++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt
@@ -67,6 +67,7 @@
 import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS
 import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERRIDE_CANNOT_BE_STATIC
 import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION
+import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REDUNDANT_REPEATABLE_ANNOTATION
 import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATABLE_ANNOTATION_HAS_NESTED_CLASS_NAMED_CONTAINER
 import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATABLE_CONTAINER_HAS_NON_DEFAULT_PARAMETER
 import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.REPEATABLE_CONTAINER_HAS_SHORTER_RETENTION
@@ -285,6 +286,12 @@
             JAVA_SAM_INTERFACE_CONSTRUCTOR_REFERENCE,
             "Java SAM interface constructor references are prohibited"
         )
+        map.put(
+            REDUNDANT_REPEATABLE_ANNOTATION,
+            "Please, remove the ''{0}'' annotation, as ''{1}'' is already enough",
+            TO_STRING,
+            TO_STRING,
+        )
 
         map.checkMissingMessages(FirJvmErrors)
     }
diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt
index 32a7e96..e0adbd2 100644
--- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt
+++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt
@@ -18,6 +18,7 @@
             FirJvmStaticChecker,
             FirRepeatableAnnotationChecker,
             FirJvmInvalidAndDangerousCharactersChecker,
+            FirJvmRedundantRepeatableChecker,
         )
 
     override val classCheckers: Set<FirClassChecker>
diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmRedundantRepeatableChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmRedundantRepeatableChecker.kt
new file mode 100644
index 0000000..6cda8bc
--- /dev/null
+++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmRedundantRepeatableChecker.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010-2022 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.jvm.checkers.declaration
+
+import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
+import org.jetbrains.kotlin.diagnostics.reportOn
+import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
+import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
+import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
+import org.jetbrains.kotlin.fir.declarations.*
+import org.jetbrains.kotlin.fir.expressions.classId
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Repeatable
+import org.jetbrains.kotlin.name.StandardClassIds.Annotations.JvmRepeatable
+import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Java
+
+object FirJvmRedundantRepeatableChecker : FirBasicDeclarationChecker() {
+    override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
+        val kotlinRepeatable = declaration.annotations.find { it.fullyExpandedClassId(context.session) == Repeatable }
+
+        val javaRepeatable = declaration.annotations.find {
+            val expandedClassId = it.fullyExpandedClassId(context.session)
+            expandedClassId == JvmRepeatable || expandedClassId == Java.Repeatable
+        }
+
+        if (kotlinRepeatable != null && javaRepeatable != null) {
+            reporter.reportOn(
+                kotlinRepeatable.source,
+                FirJvmErrors.REDUNDANT_REPEATABLE_ANNOTATION,
+                kotlinRepeatable.classId?.asSingleFqName() ?: FqName.ROOT,
+                javaRepeatable.classId?.asSingleFqName() ?: FqName.ROOT,
+                context
+            )
+        }
+    }
+}
+
diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirRepeatableAnnotationChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirRepeatableAnnotationChecker.kt
index 89ac62c..d8a3d4a 100644
--- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirRepeatableAnnotationChecker.kt
+++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirRepeatableAnnotationChecker.kt
@@ -17,6 +17,7 @@
 import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
 import org.jetbrains.kotlin.fir.analysis.checkers.getAnnotationRetention
 import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
+import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
 import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
 import org.jetbrains.kotlin.fir.analysis.jvm.checkers.isJvm6
 import org.jetbrains.kotlin.fir.declarations.*
@@ -24,6 +25,7 @@
 import org.jetbrains.kotlin.fir.expressions.*
 import org.jetbrains.kotlin.fir.languageVersionSettings
 import org.jetbrains.kotlin.fir.resolve.defaultType
+import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
 import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
 import org.jetbrains.kotlin.fir.scopes.getSingleClassifier
 import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
@@ -51,7 +53,8 @@
             val annotationClass = session.symbolProvider.getClassLikeSymbolByClassId(annotationClassId) ?: continue
 
             val useSiteTarget = annotation.useSiteTarget
-            val existingTargetsForAnnotation = annotationsMap.getOrPut(annotation.annotationTypeRef.coneType) { arrayListOf() }
+            val expandedType = annotation.annotationTypeRef.coneType.fullyExpandedType(context.session)
+            val existingTargetsForAnnotation = annotationsMap.getOrPut(expandedType) { arrayListOf() }
             val duplicateAnnotation = useSiteTarget in existingTargetsForAnnotation ||
                     existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) }
 
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt
index 78a8215..65a1594 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirAnnotationHelpers.kt
@@ -185,7 +185,8 @@
 
     for (annotation in annotations) {
         val useSiteTarget = annotation.useSiteTarget ?: annotationContainer?.getDefaultUseSiteTarget(annotation, context)
-        val existingTargetsForAnnotation = annotationsMap.getOrPut(annotation.annotationTypeRef.coneType) { arrayListOf() }
+        val expandedType = annotation.annotationTypeRef.coneType.fullyExpandedType(context.session)
+        val existingTargetsForAnnotation = annotationsMap.getOrPut(expandedType) { arrayListOf() }
 
         checkRepeatedAnnotation(useSiteTarget, existingTargetsForAnnotation, annotation, context, reporter)
         existingTargetsForAnnotation.add(useSiteTarget)
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt
index 8070daa..72160bc 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt
@@ -11,6 +11,7 @@
 import org.jetbrains.kotlin.fir.expressions.*
 import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
 import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
+import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
 import org.jetbrains.kotlin.fir.resolve.toSymbol
 import org.jetbrains.kotlin.fir.resolvedSymbol
 import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
@@ -223,3 +224,6 @@
     val lookupTag = it.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag ?: return@any false
     lookupTag.classId == LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_CLASS_ID
 }
+
+fun FirAnnotation.fullyExpandedClassId(useSiteSession: FirSession): ClassId? =
+    coneClassLikeType?.fullyExpandedType(useSiteSession)?.classId
diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt
index 3014402..53d445a 100644
--- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt
+++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/RepeatableAnnotationChecker.kt
@@ -12,10 +12,7 @@
 import org.jetbrains.kotlin.config.LanguageVersionSettings
 import org.jetbrains.kotlin.descriptors.ClassDescriptor
 import org.jetbrains.kotlin.descriptors.ModuleDescriptor
-import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
-import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
-import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
-import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
+import org.jetbrains.kotlin.descriptors.annotations.*
 import org.jetbrains.kotlin.diagnostics.Diagnostic
 import org.jetbrains.kotlin.incremental.components.NoLookupLocation
 import org.jetbrains.kotlin.lexer.KtTokens
@@ -73,6 +70,15 @@
                     javaRepeatable != null -> checkJavaRepeatableAnnotationDeclaration(javaRepeatable, annotationClass, trace)
                     kotlinRepeatable != null -> checkKotlinRepeatableAnnotationDeclaration(kotlinRepeatable, annotationClass, trace)
                 }
+                if (javaRepeatable != null && kotlinRepeatable != null) {
+                    trace.report(
+                        ErrorsJvm.REDUNDANT_REPEATABLE_ANNOTATION.on(
+                            kotlinRepeatable.entry,
+                            kotlinRepeatable.descriptor.abbreviationFqName ?: FqName.ROOT,
+                            javaRepeatable.descriptor.abbreviationFqName ?: FqName.ROOT,
+                        )
+                    )
+                }
             }
         }
     }
diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java
index a562c8b..314ec7f 100644
--- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java
+++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java
@@ -232,6 +232,9 @@
 
         MAP.put(JAVA_SAM_INTERFACE_CONSTRUCTOR_REFERENCE, "Java SAM interface constructor references are prohibited");
         MAP.put(ENUM_DECLARING_CLASS_DEPRECATED, "Enum.declaringClass is deprecated, use declaringJavaClass instead or cast receiver to java.lang.Enum explicitly");
+
+        MAP.put(REDUNDANT_REPEATABLE_ANNOTATION,
+                "Please, remove the ''{0}'' annotation, as ''{1}'' is already enough", TO_STRING, TO_STRING);
     }
 
     @NotNull
diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java
index 2e33065..edd7eff 100644
--- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java
+++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java
@@ -210,6 +210,8 @@
     DiagnosticFactoryForDeprecation0<PsiElement> ENUM_DECLARING_CLASS_DEPRECATED =
             DiagnosticFactoryForDeprecation0.create(LanguageFeature.ProhibitEnumDeclaringClass);
 
+    DiagnosticFactory2<KtAnnotationEntry, FqName, FqName> REDUNDANT_REPEATABLE_ANNOTATION = DiagnosticFactory2.create(WARNING);
+
     @SuppressWarnings("UnusedDeclaration")
     Object _initializer = new Object() {
         {
diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt
index cbbe9d2..d3158e6 100644
--- a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt
+++ b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_5.kt
@@ -14,7 +14,7 @@
 }
 annotation class D1(val value: Array<B1>)
 
-@Repeatable
+<!REDUNDANT_REPEATABLE_ANNOTATION!>@Repeatable<!>
 @java.lang.annotation.Repeatable(D2::class)
 annotation class B2 {
     class Container
diff --git a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt
index c2b5217..e7e466f 100644
--- a/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt
+++ b/compiler/testData/diagnostics/tests/annotations/repeatable/nestedClassContainer_1_6.kt
@@ -14,7 +14,7 @@
 }
 annotation class D1(val value: Array<B1>)
 
-@Repeatable
+<!REDUNDANT_REPEATABLE_ANNOTATION!>@Repeatable<!>
 @java.lang.annotation.Repeatable(D2::class)
 annotation class B2 {
     class Container
diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.kt
new file mode 100644
index 0000000..86ce9a4
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.kt
@@ -0,0 +1,27 @@
+// FIR_IDENTICAL
+// FULL_JDK
+
+<!REDUNDANT_REPEATABLE_ANNOTATION!>@kotlin.annotation.Repeatable<!>
+@java.lang.annotation.Repeatable(AContainer::class)
+annotation class A
+annotation class AContainer(val value: Array<A>)
+
+<!REDUNDANT_REPEATABLE_ANNOTATION!>@kotlin.annotation.Repeatable<!>
+@kotlin.jvm.JvmRepeatable(BContainer::class)
+annotation class B
+annotation class BContainer(val value: Array<B>)
+
+<!REDUNDANT_REPEATABLE_ANNOTATION!>@kotlin.annotation.Repeatable<!>
+<!REPEATED_ANNOTATION!>@kotlin.annotation.Repeatable<!>
+@kotlin.jvm.JvmRepeatable(CContainer::class)
+<!REPEATED_ANNOTATION!>@java.lang.annotation.Repeatable(CContainer::class)<!>
+annotation class C
+annotation class CContainer(val value: Array<C>)
+
+typealias AlphaRepeatable = kotlin.annotation.Repeatable
+typealias BetaRepeatable = kotlin.jvm.JvmRepeatable
+
+<!REDUNDANT_REPEATABLE_ANNOTATION!>@AlphaRepeatable<!>
+@BetaRepeatable(DContainer::class)
+annotation class D
+annotation class DContainer(val value: Array<D>)
diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.txt
new file mode 100644
index 0000000..e37f2be
--- /dev/null
+++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.txt
@@ -0,0 +1,64 @@
+package
+
+@kotlin.annotation.Repeatable @java.lang.annotation.Repeatable(value = AContainer::class) public final annotation class A : kotlin.Annotation {
+    public constructor A()
+    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 final annotation class AContainer : kotlin.Annotation {
+    public constructor AContainer(/*0*/ value: kotlin.Array<A>)
+    public final val value: kotlin.Array<A>
+    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
+}
+
+@kotlin.annotation.Repeatable @kotlin.jvm.JvmRepeatable /* = java.lang.annotation.Repeatable */(value = BContainer::class) public final annotation class B : kotlin.Annotation {
+    public constructor B()
+    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 final annotation class BContainer : kotlin.Annotation {
+    public constructor BContainer(/*0*/ value: kotlin.Array<B>)
+    public final val value: kotlin.Array<B>
+    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
+}
+
+@kotlin.annotation.Repeatable @kotlin.annotation.Repeatable @kotlin.jvm.JvmRepeatable /* = java.lang.annotation.Repeatable */(value = CContainer::class) @java.lang.annotation.Repeatable(value = CContainer::class) public final annotation class C : kotlin.Annotation {
+    public constructor C()
+    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 final annotation class CContainer : kotlin.Annotation {
+    public constructor CContainer(/*0*/ value: kotlin.Array<C>)
+    public final val value: kotlin.Array<C>
+    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
+}
+
+@AlphaRepeatable /* = kotlin.annotation.Repeatable */ @BetaRepeatable /* = java.lang.annotation.Repeatable */(value = DContainer::class) public final annotation class D : kotlin.Annotation {
+    public constructor D()
+    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 final annotation class DContainer : kotlin.Annotation {
+    public constructor DContainer(/*0*/ value: kotlin.Array<D>)
+    public final val value: kotlin.Array<D>
+    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 typealias AlphaRepeatable = kotlin.annotation.Repeatable
+public typealias BetaRepeatable = kotlin.jvm.JvmRepeatable
+
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 5e96434..5ed95ca 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
@@ -34957,6 +34957,12 @@
             }
 
             @Test
+            @TestMetadata("multipleRepeatables.kt")
+            public void testMultipleRepeatables() throws Exception {
+                runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/multipleRepeatables.kt");
+            }
+
+            @Test
             @TestMetadata("qualifiedCallValue.kt")
             public void testQualifiedCallValue() throws Exception {
                 runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/qualifiedCallValue.kt");