From c57c34525fab8e246c8847a9a3317f400426d47b Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Fri, 19 May 2023 11:33:17 +0000 Subject: [PATCH] [K/N] KT-58562: Implement frontend checkers for HiddenFromObjC on classes --- .../diagnostics/FirNativeDiagnosticsList.kt | 4 +- .../diagnostics/native/FirNativeErrors.kt | 4 +- .../native/FirNativeErrorsDefaultMessages.kt | 13 +- ...rNativeHiddenFromObjCInheritanceChecker.kt | 72 ++++++++ ...irNativeObjCRefinementAnnotationChecker.kt | 49 ++++-- .../checkers/NativeDeclarationCheckers.kt | 3 +- .../diagnostics/nativeTests/objCRefinement.kt | 74 +++++++- .../nativeTests/objCRefinement.txt | 164 +++++++++++++++++- .../lower/SpecialBackendChecksTraversal.kt | 27 --- .../diagnostics/DefaultErrorMessagesNative.kt | 12 +- .../resolve/konan/diagnostics/ErrorsNative.kt | 6 +- .../NativeHiddenFromObjCInheritanceChecker.kt | 61 +++++++ .../NativeObjCRefinementAnnotationChecker.kt | 59 ++++--- .../platform/NativePlatformConfigurator.kt | 2 +- 14 files changed, 465 insertions(+), 85 deletions(-) create mode 100644 compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeHiddenFromObjCInheritanceChecker.kt create mode 100644 native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/NativeHiddenFromObjCInheritanceChecker.kt diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirNativeDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirNativeDiagnosticsList.kt index 4001b2b0adf..3e9913698b2 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirNativeDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirNativeDiagnosticsList.kt @@ -46,7 +46,6 @@ object NATIVE_DIAGNOSTICS_LIST : DiagnosticList("FirNativeErrors") { parameter>("declaration") parameter>("containingClasses") } - val INVALID_OBJC_REFINEMENT_TARGETS by error() val INAPPLICABLE_OBJC_NAME by error() val INVALID_OBJC_NAME by error() val INVALID_OBJC_NAME_CHARS by error { @@ -63,5 +62,8 @@ object NATIVE_DIAGNOSTICS_LIST : DiagnosticList("FirNativeErrors") { val INAPPLICABLE_EXACT_OBJC_NAME by error() val MISSING_EXACT_OBJC_NAME by error() val NON_LITERAL_OBJC_NAME_ARG by error() + val INVALID_OBJC_HIDES_TARGETS by error() + val INVALID_REFINES_IN_SWIFT_TARGETS by error() + val SUBTYPE_OF_HIDDEN_FROM_OBJC by error() } } diff --git a/compiler/fir/checkers/checkers.native/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/native/FirNativeErrors.kt b/compiler/fir/checkers/checkers.native/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/native/FirNativeErrors.kt index e562d32d2f8..81ac5b8ae58 100644 --- a/compiler/fir/checkers/checkers.native/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/native/FirNativeErrors.kt +++ b/compiler/fir/checkers/checkers.native/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/native/FirNativeErrors.kt @@ -35,7 +35,6 @@ object FirNativeErrors { val INVALID_CHARACTERS_NATIVE by deprecationError1(ProhibitInvalidCharsInNativeIdentifiers, SourceElementPositioningStrategies.NAME_IDENTIFIER) val REDUNDANT_SWIFT_REFINEMENT by error0() val INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE by error2, Collection>() - val INVALID_OBJC_REFINEMENT_TARGETS by error0() val INAPPLICABLE_OBJC_NAME by error0() val INVALID_OBJC_NAME by error0() val INVALID_OBJC_NAME_CHARS by error1() @@ -45,6 +44,9 @@ object FirNativeErrors { val INAPPLICABLE_EXACT_OBJC_NAME by error0() val MISSING_EXACT_OBJC_NAME by error0() val NON_LITERAL_OBJC_NAME_ARG by error0() + val INVALID_OBJC_HIDES_TARGETS by error0() + val INVALID_REFINES_IN_SWIFT_TARGETS by error0() + val SUBTYPE_OF_HIDDEN_FROM_OBJC by error0() init { RootDiagnosticRendererFactory.registerFactory(FirNativeErrorsDefaultMessages) diff --git a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/diagnostics/native/FirNativeErrorsDefaultMessages.kt b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/diagnostics/native/FirNativeErrorsDefaultMessages.kt index 91eba98924f..d16487640e4 100644 --- a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/diagnostics/native/FirNativeErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/diagnostics/native/FirNativeErrorsDefaultMessages.kt @@ -22,14 +22,16 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INCO import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INCOMPATIBLE_THROWS_INHERITED import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INCOMPATIBLE_THROWS_OVERRIDE import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_CHARACTERS_NATIVE +import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_HIDES_TARGETS import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_NAME_CHARS import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_NAME_FIRST_CHAR -import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_OBJC_REFINEMENT_TARGETS +import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INVALID_REFINES_IN_SWIFT_TARGETS import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.MISSING_EXACT_OBJC_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.REDUNDANT_SWIFT_REFINEMENT import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.NON_LITERAL_OBJC_NAME_ARG +import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.SUBTYPE_OF_HIDDEN_FROM_OBJC import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.THROWS_LIST_EMPTY object FirNativeErrorsDefaultMessages : BaseDiagnosticRendererFactory() { @@ -60,8 +62,12 @@ object FirNativeErrorsDefaultMessages : BaseDiagnosticRendererFactory() { SYMBOLS ) map.put( - INVALID_OBJC_REFINEMENT_TARGETS, - "Refines annotations are only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY" + INVALID_OBJC_HIDES_TARGETS, + "@HidesFromObjC annotation is only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY" + ) + map.put( + INVALID_REFINES_IN_SWIFT_TARGETS, + "@RefinesInSwift annotation is only applicable to annotations with targets FUNCTION and/or PROPERTY" ) map.put(INAPPLICABLE_OBJC_NAME, "@ObjCName is not applicable on overrides") map.put(INVALID_OBJC_NAME, "@ObjCName should have a name and/or swiftName") @@ -72,5 +78,6 @@ object FirNativeErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(INAPPLICABLE_EXACT_OBJC_NAME, "Exact @ObjCName is only applicable to classes, objects and interfaces") map.put(MISSING_EXACT_OBJC_NAME, "Exact @ObjCName is required to have an ObjC name") map.put(NON_LITERAL_OBJC_NAME_ARG, "@ObjCName accepts only literal string and boolean values") + map.put(SUBTYPE_OF_HIDDEN_FROM_OBJC, "Only @HiddenFromObjC declaration can be a subtype of @HiddenFromObjC declaration") } } diff --git a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeHiddenFromObjCInheritanceChecker.kt b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeHiddenFromObjCInheritanceChecker.kt new file mode 100644 index 00000000000..b30edfbb3d7 --- /dev/null +++ b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeHiddenFromObjCInheritanceChecker.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2023 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.native.checkers + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.classKind +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol +import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.toAnnotationClassLikeSymbol +import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes +import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.types.* + +/** + * Check that the given class does not inherit from class or implements interface that is + * marked as HiddenFromObjC (aka "marked with annotation that is marked as HidesFromObjC"). + */ +object FirNativeHiddenFromObjCInheritanceChecker : FirRegularClassChecker() { + override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { + // Enum entries inherit from their enum class. + if (declaration.classKind == ClassKind.ENUM_ENTRY) { + return + } + // Non-public types do not leak to Objective-C API surface, so it is OK for them + // to inherit from hidden types. + if (!declaration.visibility.isPublicAPI) return + val session = context.session + // No need to report anything on class that is hidden itself. + if (checkIsHiddenFromObjC(declaration.symbol, session)) { + return + } + + val superTypes = declaration.superConeTypes + .filterNot { it.isAny || it.isNullableAny } + .mapNotNull { it.toSymbol(session) } + + superTypes.firstOrNull { st -> checkIsHiddenFromObjC(st, session) }?.let { + reporter.reportOn(declaration.source, FirNativeErrors.SUBTYPE_OF_HIDDEN_FROM_OBJC, context) + } + } +} + +private fun checkContainingClassIsHidden(classSymbol: FirClassLikeSymbol<*>, session: FirSession): Boolean { + return classSymbol.getContainingClassSymbol(session)?.let { + if (checkIsHiddenFromObjC(it, session)) { + true + } else { + checkContainingClassIsHidden(it, session) + } + } ?: false +} + +private fun checkIsHiddenFromObjC(classSymbol: FirClassLikeSymbol<*>, session: FirSession): Boolean { + classSymbol.annotations.forEach { annotation -> + val annotationClass = annotation.toAnnotationClassLikeSymbol(session) ?: return@forEach + val objCExportMetaAnnotations = annotationClass.annotations.findMetaAnnotations(session) + if (objCExportMetaAnnotations.hidesFromObjCAnnotation != null) { + return true + } + } + return checkContainingClassIsHidden(classSymbol, session) +} \ No newline at end of file diff --git a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeObjCRefinementAnnotationChecker.kt b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeObjCRefinementAnnotationChecker.kt index c845a858930..1d3bd3d1c20 100644 --- a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeObjCRefinementAnnotationChecker.kt +++ b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeObjCRefinementAnnotationChecker.kt @@ -6,9 +6,11 @@ package org.jetbrains.kotlin.fir.analysis.native.checkers import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker @@ -21,12 +23,13 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation object FirNativeObjCRefinementAnnotationChecker : FirRegularClassChecker() { - private val supportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS) + private val hidesFromObjCSupportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS) + private val refinesInSwiftSupportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY) override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration.classKind != ClassKind.ANNOTATION_CLASS) return val session = context.session - val (objCAnnotation, swiftAnnotation) = declaration.findMetaAnnotations(session) + val (objCAnnotation, swiftAnnotation) = declaration.annotations.findMetaAnnotations(session) if (objCAnnotation == null && swiftAnnotation == null) return if (objCAnnotation != null && swiftAnnotation != null) { reporter.reportOn( @@ -36,23 +39,35 @@ object FirNativeObjCRefinementAnnotationChecker : FirRegularClassChecker() { ) } val targets = declaration.getAllowedAnnotationTargets(session) - val unsupportedTargets = targets - supportedTargets - if (unsupportedTargets.isNotEmpty()) { - objCAnnotation?.let { reporter.reportOn(it.source, FirNativeErrors.INVALID_OBJC_REFINEMENT_TARGETS, context) } - swiftAnnotation?.let { reporter.reportOn(it.source, FirNativeErrors.INVALID_OBJC_REFINEMENT_TARGETS, context) } - } - } - private fun FirRegularClass.findMetaAnnotations(session: FirSession): Pair { - var objCAnnotation: FirAnnotation? = null - var swiftAnnotation: FirAnnotation? = null - for (annotation in annotations) { - when (annotation.toAnnotationClassId(session)) { - hidesFromObjCClassId -> objCAnnotation = annotation - refinesInSwiftClassId -> swiftAnnotation = annotation + objCAnnotation?.let { + if ((targets - hidesFromObjCSupportedTargets).isNotEmpty()) { + reporter.reportOn(it.source, FirNativeErrors.INVALID_OBJC_HIDES_TARGETS, context) + } + } + swiftAnnotation?.let { + if ((targets - refinesInSwiftSupportedTargets).isNotEmpty()) { + reporter.reportOn(it.source, FirNativeErrors.INVALID_REFINES_IN_SWIFT_TARGETS, context) } - if (objCAnnotation != null && swiftAnnotation != null) break } - return objCAnnotation to swiftAnnotation } } + +internal data class ObjCExportMetaAnnotations( + val hidesFromObjCAnnotation: FirAnnotation?, + val refinesInSwiftAnnotation: FirAnnotation?, +) + +internal fun List.findMetaAnnotations(session: FirSession): ObjCExportMetaAnnotations { + var objCAnnotation: FirAnnotation? = null + var swiftAnnotation: FirAnnotation? = null + for (annotation in this) { + when (annotation.toAnnotationClassId(session)) { + hidesFromObjCClassId -> objCAnnotation = annotation + refinesInSwiftClassId -> swiftAnnotation = annotation + } + if (objCAnnotation != null && swiftAnnotation != null) break + } + return ObjCExportMetaAnnotations(objCAnnotation, swiftAnnotation) +} + diff --git a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/NativeDeclarationCheckers.kt b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/NativeDeclarationCheckers.kt index cd7be4992a4..7693482d917 100644 --- a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/NativeDeclarationCheckers.kt +++ b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/NativeDeclarationCheckers.kt @@ -30,6 +30,7 @@ object NativeDeclarationCheckers : DeclarationCheckers() { override val regularClassCheckers: Set get() = setOf( - FirNativeObjCRefinementAnnotationChecker + FirNativeObjCRefinementAnnotationChecker, + FirNativeHiddenFromObjCInheritanceChecker, ) } diff --git a/compiler/testData/diagnostics/nativeTests/objCRefinement.kt b/compiler/testData/diagnostics/nativeTests/objCRefinement.kt index 25d854b530f..0525fd2f1f6 100644 --- a/compiler/testData/diagnostics/nativeTests/objCRefinement.kt +++ b/compiler/testData/diagnostics/nativeTests/objCRefinement.kt @@ -8,7 +8,7 @@ package kotlin.native annotation class HidesFromObjC @HidesFromObjC -@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) @Retention(AnnotationRetention.BINARY) annotation class HiddenFromObjC @@ -21,6 +21,11 @@ annotation class RefinesInSwift @Retention(AnnotationRetention.BINARY) public annotation class ShouldRefineInSwift +@RefinesInSwift +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public annotation class WrongShouldRefineInSwift + // FILE: plugin.kt package plugin @@ -44,12 +49,12 @@ import plugin.PluginShouldRefineInSwift @Retention(AnnotationRetention.BINARY) annotation class MyRefinedAnnotationA -@HidesFromObjC +@HidesFromObjC @Target(AnnotationTarget.PROPERTY, AnnotationTarget.FILE) @Retention(AnnotationRetention.BINARY) annotation class MyRefinedAnnotationB -@RefinesInSwift +@RefinesInSwift @Retention(AnnotationRetention.BINARY) annotation class MyRefinedAnnotationC @@ -132,3 +137,66 @@ interface I { open class Derived2 : Derived() { override fun foo() {} } + +@HiddenFromObjC +open class OpenHiddenClass + +class InheritsFromOpenHiddenClass : OpenHiddenClass() + +@HiddenFromObjC +interface HiddenInterface + +interface NotHiddenInterface + +class ImplementsHiddenInterface : NotHiddenInterface, HiddenInterface + +class InheritsFromOpenHiddenClass2 : NotHiddenInterface, OpenHiddenClass() + +@HiddenFromObjC +class OuterHidden { + class Nested { + open class Nested + } +} + +class InheritsFromNested : OuterHidden.Nested.Nested() + +private class PrivateInheritsFromNested : OuterHidden.Nested.Nested() + +internal class InternalInheritsFromNested : OuterHidden.Nested.Nested() + +fun produceInstanceOfHidden(): OuterHidden.Nested.Nested { + return object : OuterHidden.Nested.Nested() {} +} + +@HiddenFromObjC +enum class MyHiddenEnum { + A, + B, + C +} + +@HiddenFromObjC +object MyHiddenObject + +sealed class MySealedClass { + @HiddenFromObjC + class MyHiddenSealedVariant : MySealedClass() + + class MyPublicVariant : MySealedClass() +} + +@HiddenFromObjC +enum class MyHiddenNonTrivialEnum { + A, + B, + C { + override fun sayCheese(): String { + return "Boo :(" + } + }; + + open fun sayCheese(): String { + return "Cheese!" + } +} diff --git a/compiler/testData/diagnostics/nativeTests/objCRefinement.txt b/compiler/testData/diagnostics/nativeTests/objCRefinement.txt index 532511f2665..c579afa03bd 100644 --- a/compiler/testData/diagnostics/nativeTests/objCRefinement.txt +++ b/compiler/testData/diagnostics/nativeTests/objCRefinement.txt @@ -5,6 +5,7 @@ package @kotlin.native.HiddenFromObjC @plugin.PluginHiddenFromObjC public fun multipleObjCRefinementsFunction(): kotlin.Unit @kotlin.native.ShouldRefineInSwift @plugin.PluginShouldRefineInSwift public fun multipleSwiftRefinementsFunction(): kotlin.Unit @plugin.PluginHiddenFromObjC @plugin.PluginShouldRefineInSwift public fun pluginRefinedFunction(): kotlin.Unit +public fun produceInstanceOfHidden(): OuterHidden.Nested.Nested public open class Base { public constructor Base() @@ -54,6 +55,12 @@ public open class Derived2 : Derived { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +@kotlin.native.HiddenFromObjC public interface HiddenInterface { + 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 I { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public abstract fun foo(): kotlin.Unit @@ -61,6 +68,34 @@ public interface I { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +public final class ImplementsHiddenInterface : NotHiddenInterface, HiddenInterface { + public constructor ImplementsHiddenInterface() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class InheritsFromNested : OuterHidden.Nested.Nested { + public constructor InheritsFromNested() + 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 class InheritsFromOpenHiddenClass : OpenHiddenClass { + public constructor InheritsFromOpenHiddenClass() + 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 class InheritsFromOpenHiddenClass2 : NotHiddenInterface, OpenHiddenClass { + public constructor InheritsFromOpenHiddenClass2() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + public interface InterfaceA { public abstract val barA: kotlin.Int public abstract val barB: kotlin.Int @@ -81,6 +116,63 @@ public interface InterfaceB { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +internal final class InternalInheritsFromNested : OuterHidden.Nested.Nested { + public constructor InternalInheritsFromNested() + 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.native.HiddenFromObjC public final enum class MyHiddenEnum : kotlin.Enum { + enum entry A + + enum entry B + + enum entry C + + private constructor MyHiddenEnum() + @kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyHiddenEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): MyHiddenEnum + public final /*synthesized*/ fun values(): kotlin.Array +} + +@kotlin.native.HiddenFromObjC public final enum class MyHiddenNonTrivialEnum : kotlin.Enum { + enum entry A + + enum entry B + + enum entry C + + private constructor MyHiddenNonTrivialEnum() + @kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyHiddenNonTrivialEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open fun sayCheese(): kotlin.String + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): MyHiddenNonTrivialEnum + public final /*synthesized*/ fun values(): kotlin.Array +} + +@kotlin.native.HiddenFromObjC public object MyHiddenObject { + private constructor MyHiddenObject() + 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.native.HidesFromObjC @kotlin.native.RefinesInSwift @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class MyRefinedAnnotationA : kotlin.Annotation { public constructor MyRefinedAnnotationA() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean @@ -108,13 +200,75 @@ public interface InterfaceB { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +public sealed class MySealedClass { + protected constructor MySealedClass() + 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.native.HiddenFromObjC public final class MyHiddenSealedVariant : MySealedClass { + public constructor MyHiddenSealedVariant() + 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 class MyPublicVariant : MySealedClass { + public constructor MyPublicVariant() + 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 NotHiddenInterface { + 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.native.HiddenFromObjC public open class OpenHiddenClass { + public constructor OpenHiddenClass() + 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.native.HiddenFromObjC public final class OuterHidden { + public constructor OuterHidden() + 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 class Nested { + public constructor Nested() + 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 open class Nested { + public constructor Nested() + 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 + } + } +} + +private final class PrivateInheritsFromNested : OuterHidden.Nested.Nested { + public constructor PrivateInheritsFromNested() + 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 HFOC = kotlin.native.HiddenFromObjC package kotlin { package kotlin.native { - @kotlin.native.HidesFromObjC @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class HiddenFromObjC : kotlin.Annotation { + @kotlin.native.HidesFromObjC @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class HiddenFromObjC : kotlin.Annotation { public constructor HiddenFromObjC() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -141,6 +295,13 @@ package kotlin { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + + @kotlin.native.RefinesInSwift @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class WrongShouldRefineInSwift : kotlin.Annotation { + public constructor WrongShouldRefineInSwift() + 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 + } } } @@ -160,3 +321,4 @@ package plugin { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } } + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt index 18c398099f0..fca251bd024 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt @@ -596,36 +596,9 @@ private class BackendChecker( if (declaration.isKotlinObjCClass()) { checkKotlinObjCClass(declaration) } - checkHiddenFromObjCRestrictions(declaration) super.visitClass(declaration) } - - private fun IrClass.isHiddenFromObjC(): Boolean { - return annotations.any { annotationCall -> - val annotationClass = annotationCall.symbol.owner.parentAsClass - annotationClass.annotations.hasAnnotation(KonanFqNames.hidesFromObjC) - } - } - - private fun checkHiddenFromObjCRestrictions(declaration: IrClass) { - // If declaration itself. is marked as hidden, we don't need to do anything - if (declaration.isHiddenFromObjC()) return - // Enum entries inherit from their classes, so if enum class is marked as hidden, there is no need to - // produce additional errors. - if (declaration.kind == ClassKind.ENUM_ENTRY) return - // Private and local classes does not leak to Objective-C API surface, so it is OK for them - // to inherit from hidden types. - if (DescriptorVisibilities.isPrivate(declaration.visibility) || declaration.isLocal) return - if (declaration.superClass?.isHiddenFromObjC() == true) { - reportError(declaration, "Only @HiddenFromObjC declaration can inherit from class annotated with @HiddenFromObjC") - } - declaration.getSuperInterfaces().forEach { - if (it.isHiddenFromObjC()) { - reportError(declaration, "Only @HiddenFromObjC declaration can implement interface annotated with @HiddenFromObjC") - } - } - } } private fun BackendChecker.checkCanGenerateCCall(expression: IrCall, isInvoke: Boolean) { diff --git a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/DefaultErrorMessagesNative.kt b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/DefaultErrorMessagesNative.kt index 767820e0e7f..b7bfeffd32b 100644 --- a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/DefaultErrorMessagesNative.kt +++ b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/DefaultErrorMessagesNative.kt @@ -63,8 +63,16 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy { CommonRenderers.commaSeparated(Renderers.NAME) ) put( - ErrorsNative.INVALID_OBJC_REFINEMENT_TARGETS, - "Refines annotations are only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY" + ErrorsNative.INVALID_OBJC_HIDES_TARGETS, + "@HidesFromObjC annotation is only applicable to annotations with targets CLASS, FUNCTION and/or PROPERTY" + ) + put( + ErrorsNative.INVALID_REFINES_IN_SWIFT_TARGETS, + "@RefinesInSwift annotation is only applicable to annotations with targets FUNCTION and/or PROPERTY" + ) + put( + ErrorsNative.SUBTYPE_OF_HIDDEN_FROM_OBJC, + "Only @HiddenFromObjC declaration can be a subtype of @HiddenFromObjC declaration" ) } } diff --git a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/ErrorsNative.kt b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/ErrorsNative.kt index 460ec90e13c..ee0f23a7509 100644 --- a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/ErrorsNative.kt +++ b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/ErrorsNative.kt @@ -59,7 +59,11 @@ object ErrorsNative { @JvmField val INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE = DiagnosticFactory2.create>(Severity.ERROR) @JvmField - val INVALID_OBJC_REFINEMENT_TARGETS = DiagnosticFactory0.create(Severity.ERROR) + val INVALID_OBJC_HIDES_TARGETS = DiagnosticFactory0.create(Severity.ERROR) + @JvmField + val INVALID_REFINES_IN_SWIFT_TARGETS = DiagnosticFactory0.create(Severity.ERROR) + @JvmField + val SUBTYPE_OF_HIDDEN_FROM_OBJC = DiagnosticFactory0.create(Severity.ERROR) init { Errors.Initializer.initializeFactoryNames(ErrorsNative::class.java) diff --git a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/NativeHiddenFromObjCInheritanceChecker.kt b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/NativeHiddenFromObjCInheritanceChecker.kt new file mode 100644 index 00000000000..dfdf3558b1c --- /dev/null +++ b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/NativeHiddenFromObjCInheritanceChecker.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2023 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.resolve.konan.diagnostics + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry +import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker +import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext +import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces + +/** + * Check that the given class does not inherit from class or implements interface that is + * marked as HiddenFromObjC (aka "marked with annotation that is marked as HidesFromObjC"). + */ +object NativeHiddenFromObjCInheritanceChecker : DeclarationChecker { + override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { + if (descriptor !is ClassDescriptor) return + // Enum entries inherit from their enum class. + if (descriptor.kind == ClassKind.ENUM_ENTRY) return + // Non-public types do not leak to Objective-C API surface, so it is OK for them + // to inherit from hidden types. + if (!descriptor.visibility.isPublicAPI) return + // No need to report anything on class that is hidden itself. + if (checkClassIsHiddenFromObjC(descriptor)) return + + val isSubtypeOfHiddenFromObjC = descriptor.getSuperInterfaces().any { checkClassIsHiddenFromObjC(it) } || + descriptor.getSuperClassNotAny()?.let { checkClassIsHiddenFromObjC(it) } == true + if (isSubtypeOfHiddenFromObjC) { + context.trace.report(ErrorsNative.SUBTYPE_OF_HIDDEN_FROM_OBJC.on(declaration)) + } + } +} + +private fun checkContainingClassIsHidden(currentClass: ClassDescriptor): Boolean { + return (currentClass.containingDeclaration as? ClassDescriptor)?.let { + if (checkClassIsHiddenFromObjC(it)) { + true + } else { + checkContainingClassIsHidden(it) + } + } ?: false +} + +private fun checkClassIsHiddenFromObjC(clazz: ClassDescriptor): Boolean { + clazz.annotations.forEach { annotation -> + val objcExportMetaAnnotations = annotation.annotationClass?.findObjCExportMetaAnnotations() + ?: return@forEach + if (objcExportMetaAnnotations.hidesFromObjCAnnotation != null) { + return true + } + } + // If outer class is hidden then inner/nested class is hidden as well. + return checkContainingClassIsHidden(clazz) +} \ No newline at end of file diff --git a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/NativeObjCRefinementAnnotationChecker.kt b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/NativeObjCRefinementAnnotationChecker.kt index 18ce765dda1..308368e57a0 100644 --- a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/NativeObjCRefinementAnnotationChecker.kt +++ b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/diagnostics/NativeObjCRefinementAnnotationChecker.kt @@ -12,51 +12,56 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.resolve.AnnotationChecker -import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCRefinementChecker.hidesFromObjCFqName import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCRefinementChecker.refinesInSwiftFqName +internal data class ObjCExportMetaAnnotations( + val hidesFromObjCAnnotation: AnnotationDescriptor?, + val refinesInSwiftAnnotation: AnnotationDescriptor?, +) + +internal fun DeclarationDescriptor.findObjCExportMetaAnnotations(): ObjCExportMetaAnnotations { + require(this is ClassDescriptor && this.kind == ClassKind.ANNOTATION_CLASS) + var objCAnnotation: AnnotationDescriptor? = null + var swiftAnnotation: AnnotationDescriptor? = null + for (annotation in annotations) { + when (annotation.fqName) { + hidesFromObjCFqName -> objCAnnotation = annotation + refinesInSwiftFqName -> swiftAnnotation = annotation + } + if (objCAnnotation != null && swiftAnnotation != null) break + } + return ObjCExportMetaAnnotations(objCAnnotation, swiftAnnotation) +} + object NativeObjCRefinementAnnotationChecker : DeclarationChecker { - private val supportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS) + private val hidesFromObjCSupportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY, KotlinTarget.CLASS) + private val refinesInSwiftSupportedTargets = arrayOf(KotlinTarget.FUNCTION, KotlinTarget.PROPERTY) override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { if (descriptor !is ClassDescriptor || descriptor.kind != ClassKind.ANNOTATION_CLASS) return - val (objCAnnotation, swiftAnnotation) = descriptor.findRefinesAnnotations() + val (objCAnnotation, swiftAnnotation) = descriptor.findObjCExportMetaAnnotations() if (objCAnnotation == null && swiftAnnotation == null) return if (objCAnnotation != null && swiftAnnotation != null) { val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(swiftAnnotation) ?: declaration context.trace.report(ErrorsNative.REDUNDANT_SWIFT_REFINEMENT.on(reportLocation)) } val targets = AnnotationChecker.applicableTargetSet(descriptor) - val unsupportedTargets = targets - supportedTargets - if (unsupportedTargets.isNotEmpty()) { - objCAnnotation?.let { context.trace.reportInvalidAnnotationTargets(declaration, it) } - swiftAnnotation?.let { context.trace.reportInvalidAnnotationTargets(declaration, it) } - } - } - - private fun DeclarationDescriptor.findRefinesAnnotations(): Pair { - var objCAnnotation: AnnotationDescriptor? = null - var swiftAnnotation: AnnotationDescriptor? = null - for (annotation in annotations) { - when (annotation.fqName) { - hidesFromObjCFqName -> objCAnnotation = annotation - refinesInSwiftFqName -> swiftAnnotation = annotation + objCAnnotation?.let { + if ((targets - hidesFromObjCSupportedTargets).isNotEmpty()) { + val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(it) ?: declaration + context.trace.report(ErrorsNative.INVALID_OBJC_HIDES_TARGETS.on(reportLocation)) + } + } + swiftAnnotation?.let { + if ((targets - refinesInSwiftSupportedTargets).isNotEmpty()) { + val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(it) ?: declaration + context.trace.report(ErrorsNative.INVALID_REFINES_IN_SWIFT_TARGETS.on(reportLocation)) } - if (objCAnnotation != null && swiftAnnotation != null) break } - return objCAnnotation to swiftAnnotation - } - - private fun BindingTrace.reportInvalidAnnotationTargets( - declaration: KtDeclaration, - annotation: AnnotationDescriptor - ) { - val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: declaration - report(ErrorsNative.INVALID_OBJC_REFINEMENT_TARGETS.on(reportLocation)) } } diff --git a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt index f3b58e25d53..fcb0c72171e 100644 --- a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt +++ b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt @@ -28,7 +28,7 @@ object NativePlatformConfigurator : PlatformConfiguratorBase( NativeTopLevelSingletonChecker, NativeThreadLocalChecker, NativeObjCNameChecker, NativeObjCNameOverridesChecker, NativeObjCRefinementChecker, NativeObjCRefinementAnnotationChecker, - NativeObjCRefinementOverridesChecker + NativeObjCRefinementOverridesChecker, NativeHiddenFromObjCInheritanceChecker ) ) { override fun configureModuleComponents(container: StorageComponentContainer) {