From 2694326ef879a8f64c38d0940605fb3b3e694012 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Mon, 23 Oct 2023 17:31:04 +0000 Subject: [PATCH] [Wasm] Add EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE K2 diagnostic Prohibit extending non-external types with external types (same as K1) Issue KT-56849 --- .../diagnostics/FirWasmDiagnosticsList.kt | 3 ++ .../diagnostics/wasm/FirWasmErrors.kt | 1 + .../wasm/FirWasmErrorsDefaultMessages.kt | 2 + .../FirWasmExternalInheritanceChecker.kt | 38 +++++++++++++------ .../wasmTests/jsInterop/inheritance.fir.kt | 6 +-- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirWasmDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirWasmDiagnosticsList.kt index 9e9f695ef65..74994af056f 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirWasmDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirWasmDiagnosticsList.kt @@ -20,5 +20,8 @@ object WASM_DIAGNOSTICS_LIST : DiagnosticList("FirWasmErrors") { val NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE by error(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) { parameter("superType") } + val EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE by error(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) { + parameter("superType") + } } } diff --git a/compiler/fir/checkers/checkers.wasm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrors.kt b/compiler/fir/checkers/checkers.wasm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrors.kt index 9a705ec9f9c..c5318a10c77 100644 --- a/compiler/fir/checkers/checkers.wasm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrors.kt +++ b/compiler/fir/checkers/checkers.wasm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrors.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.psi.KtElement object FirWasmErrors { // Externals val NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE by error1(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) + val EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE by error1(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) init { RootDiagnosticRendererFactory.registerFactory(FirWasmErrorsDefaultMessages) diff --git a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrorsDefaultMessages.kt b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrorsDefaultMessages.kt index 064c7fcb779..d5ce51a31f1 100644 --- a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrorsDefaultMessages.kt @@ -8,11 +8,13 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.wasm import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE @Suppress("unused") object FirWasmErrorsDefaultMessages : BaseDiagnosticRendererFactory() { override val MAP = KtDiagnosticFactoryToRendererMap("FIR").also { map -> map.put(NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE, "Non-external type extends external type {0}", FirDiagnosticRenderers.RENDER_TYPE) + map.put(EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE, "External type extends non-external type {0}", FirDiagnosticRenderers.RENDER_TYPE) } } diff --git a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmExternalInheritanceChecker.kt b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmExternalInheritanceChecker.kt index dc504d242b5..2a51abcea05 100644 --- a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmExternalInheritanceChecker.kt +++ b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmExternalInheritanceChecker.kt @@ -5,29 +5,45 @@ package org.jetbrains.kotlin.fir.analysis.wasm.checkers.declaration +import org.jetbrains.kotlin.descriptors.ClassKind 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.FirClassChecker import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors -import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.name.StandardClassIds object FirWasmExternalInheritanceChecker : FirClassChecker() { override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { val session = context.session - if (!declaration.symbol.isEffectivelyExternal(session)) { - for (superTypeRef in declaration.superTypeRefs) { - if (superTypeRef.toClassLikeSymbol(session)?.isEffectivelyExternal(session) == true) { - reporter.reportOn( - declaration.source, - FirWasmErrors.NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE, - superTypeRef.coneType, - context - ) - } + val isCurrentClassExternal = declaration.symbol.isEffectivelyExternal(session) + for (superTypeRef in declaration.superTypeRefs) { + val superClass = superTypeRef.toClassLikeSymbol(session) ?: continue + if (superClass.classId == StandardClassIds.Any) continue // External classes can extend Any + + val isSuperClassExternal = superClass.isEffectivelyExternal(session) + if (!isCurrentClassExternal && isSuperClassExternal) { + reporter.reportOn( + declaration.source, + FirWasmErrors.NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE, + superTypeRef.coneType, + context + ) + } else if (isCurrentClassExternal && !isSuperClassExternal) { + // External enum and annotation classes are prohibited, but they add implicit non-external super types. Skip reporting errors for them. + if (declaration.classKind == ClassKind.ANNOTATION_CLASS && superClass.classId == StandardClassIds.Annotation) continue + if (declaration.classKind == ClassKind.ENUM_CLASS && superClass.classId == StandardClassIds.Enum) continue + + reporter.reportOn( + declaration.source, + FirWasmErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE, + superTypeRef.coneType, + context + ) } } } diff --git a/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.fir.kt b/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.fir.kt index 674b8dccf5f..062d29f9d2d 100644 --- a/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.fir.kt +++ b/compiler/testData/diagnostics/wasmTests/jsInterop/inheritance.fir.kt @@ -4,11 +4,11 @@ interface I1 external open class EC1 -external class EC2 : C1 +external class EC2 : C1 -external class EC3 : I1, C1 +external class EC3 : I1, C1 -external interface EI1 : I1 +external interface EI1 : I1 interface I2 : EI1