diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index 98b7e7f21d7..3873b98b41a 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.container.useImpl import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.resolve.PlatformConfigurator +import org.jetbrains.kotlin.resolve.checkers.PlatformImplDeclarationChecker import org.jetbrains.kotlin.resolve.jvm.JvmOverloadFilter import org.jetbrains.kotlin.resolve.jvm.JvmTypeSpecificityComparator import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionsTypeChecker @@ -43,7 +44,8 @@ object JvmPlatformConfigurator : PlatformConfigurator( TypeParameterBoundIsNotArrayChecker(), JvmSyntheticApplicabilityChecker(), StrictfpApplicabilityChecker(), - AdditionalBuiltInsMemberOverrideDeclarationChecker + AdditionalBuiltInsMemberOverrideDeclarationChecker, + PlatformImplDeclarationChecker() ), additionalCallCheckers = listOf( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 791b1c2c8ec..f54dfc71d2a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -33,12 +33,14 @@ import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData; import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.tower.WrongResolutionToClassifier; +import org.jetbrains.kotlin.resolve.checkers.PlatformImplDeclarationChecker; import org.jetbrains.kotlin.types.KotlinType; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.List; +import java.util.Map; import static org.jetbrains.kotlin.diagnostics.PositioningStrategies.*; import static org.jetbrains.kotlin.diagnostics.Severity.ERROR; @@ -502,6 +504,11 @@ public interface Errors { DiagnosticFactory0 IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory2>> PLATFORM_DECLARATION_WITHOUT_DEFINITION = + DiagnosticFactory2.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 PLATFORM_DEFINITION_WITHOUT_DECLARATION = DiagnosticFactory0.create(ERROR); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Errors/warnings inside code blocks diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 0042210e2dc..a6457fe5869 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -268,6 +268,9 @@ public class DefaultErrorMessages { MAP.put(IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE, "Right-hand side of 'impl' type alias cannot contain use-site variance or star projections"); MAP.put(IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION, "Type arguments in the right-hand side of 'impl' type alias should be its type parameters in the same order, e.g. 'impl typealias Foo = Bar'"); + MAP.put(PLATFORM_DECLARATION_WITHOUT_DEFINITION, "No definition is found for platform declaration ''{0}''{1}", NAME, PlatformIncompatibilityDiagnosticRenderer.INSTANCE); + MAP.put(PLATFORM_DEFINITION_WITHOUT_DECLARATION, "Modifier 'impl' is only applicable to members that are initially declared in platform-independent code"); + MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties"); MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here"); MAP.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", NAME); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/PlatformIncompatibilityDiagnosticRenderer.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/PlatformIncompatibilityDiagnosticRenderer.kt new file mode 100644 index 00000000000..faabc9c6798 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/PlatformIncompatibilityDiagnosticRenderer.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.diagnostics.rendering + +import org.jetbrains.kotlin.descriptors.MemberDescriptor +import org.jetbrains.kotlin.resolve.checkers.PlatformImplDeclarationChecker + +object PlatformIncompatibilityDiagnosticRenderer : + DiagnosticParameterRenderer>> { + override fun render( + obj: Map>, + renderingContext: RenderingContext + ): String { + if (obj.isEmpty()) return "" + + return buildString { + appendln() + for ((incompatibility, descriptors) in obj) { + append("The following declaration") + if (descriptors.size == 1) append(" is") else append("s are") + append(" incompatible") + incompatibility.reason?.let { append(" because $it") } + appendln(":") + for (descriptor in descriptors) { + append(" ") + appendln(Renderers.COMPACT_WITH_MODIFIERS.render(descriptor, renderingContext)) + } + } + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PlatformImplDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PlatformImplDeclarationChecker.kt new file mode 100644 index 00000000000..95fb5755840 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PlatformImplDeclarationChecker.kt @@ -0,0 +1,315 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.resolve.checkers + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.checkers.PlatformImplDeclarationChecker.Compatibility.Compatible +import org.jetbrains.kotlin.resolve.checkers.PlatformImplDeclarationChecker.Compatibility.Incompatible +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeConstructorSubstitution +import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.typeUtil.asTypeProjection +import org.jetbrains.kotlin.utils.keysToMap + +class PlatformImplDeclarationChecker : DeclarationChecker { + override fun check( + declaration: KtDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext, + languageVersionSettings: LanguageVersionSettings + ) { + if (!languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return + + if (descriptor !is MemberDescriptor) return + + if (descriptor.isPlatform && declaration.hasModifier(KtTokens.PLATFORM_KEYWORD)) { + checkPlatformDeclarationHasDefinition(declaration, descriptor, diagnosticHolder) + } + else if (descriptor.isImpl && declaration.hasModifier(KtTokens.IMPL_KEYWORD)) { + checkImplementationHasPlatformDeclaration(declaration, descriptor, diagnosticHolder) + } + } + + private fun checkPlatformDeclarationHasDefinition( + reportOn: KtDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink + ) { + val compatibility = when (descriptor) { + is CallableMemberDescriptor -> { + descriptor.findNamesakesFromTheSameModule().filter { impl -> + descriptor != impl && + // TODO: support non-source definitions (e.g. from Java) + DescriptorToSourceUtils.getSourceFromDescriptor(impl) is KtElement + }.groupBy { impl -> + areCompatibleCallables(descriptor, impl) + } + } + is ClassDescriptor -> { + descriptor.findClassifiersFromTheSameModule().filter { impl -> + descriptor != impl && + DescriptorToSourceUtils.getSourceFromDescriptor(impl) is KtElement + }.groupBy { impl -> + areCompatibleClassifiers(descriptor, impl) + } + } + else -> null + } + + if (compatibility != null && !compatibility.containsKey(Compatible)) { + assert(compatibility.keys.all { it is Incompatible }) + @Suppress("UNCHECKED_CAST") + val incompatibility = compatibility as Map> + diagnosticHolder.report(Errors.PLATFORM_DECLARATION_WITHOUT_DEFINITION.on(reportOn, descriptor, incompatibility)) + } + } + + private fun checkImplementationHasPlatformDeclaration( + reportOn: KtDeclaration, descriptor: MemberDescriptor, diagnosticHolder: DiagnosticSink + ) { + val hasDeclaration = when (descriptor) { + is CallableMemberDescriptor -> descriptor.findNamesakesFromTheSameModule().any { declaration -> + descriptor != declaration && + declaration.isPlatform && + areCompatibleCallables(declaration, descriptor) == Compatible + } + is ClassifierDescriptor -> descriptor.findClassifiersFromTheSameModule().any { declaration -> + descriptor != declaration && + declaration is ClassDescriptor && declaration.isPlatform && + areCompatibleClassifiers(declaration, descriptor) == Compatible + } + else -> false + } + + if (!hasDeclaration) { + // TODO: do not report this error for members which are "almost compatible" with some platform declarations + diagnosticHolder.report(Errors.PLATFORM_DEFINITION_WITHOUT_DECLARATION.on(reportOn.modifierList!!.getModifier(KtTokens.IMPL_KEYWORD)!!)) + } + } + + private fun CallableMemberDescriptor.findNamesakesFromTheSameModule(): Collection { + val packageFqName = (containingDeclaration as? PackageFragmentDescriptor)?.fqName ?: return emptyList() + val myModule = this.module + val scope = myModule.getPackage(packageFqName).memberScope + + return when (this) { + is FunctionDescriptor -> scope.getContributedFunctions(name, NoLookupLocation.FOR_ALREADY_TRACKED) + is PropertyDescriptor -> scope.getContributedVariables(name, NoLookupLocation.FOR_ALREADY_TRACKED) + else -> throw AssertionError("Unsupported declaration: $this") + }.filter { + it.module == myModule // TODO: only obtain descriptors from our module to start with + } + } + + private fun ClassifierDescriptor.findClassifiersFromTheSameModule(): Collection { + // TODO: support nested classes + return module.getPackage(fqNameSafe.parent()).memberScope + .getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS) { it == name } + .filterIsInstance() + } + + sealed class Compatibility { + // Note that the reason is used in the diagnostic output, see PlatformIncompatibilityDiagnosticRenderer + sealed class Incompatible(val reason: String?) : Compatibility() { + // Callables + + object ParameterShape : Incompatible("parameter shapes are different (extension vs non-extension)") + + object ParameterCount : Incompatible("number of value parameters is different") + object TypeParameterCount : Incompatible("number of type parameters is different") + + object ParameterTypes : Incompatible("parameter types are different") + object ReturnType : Incompatible("return type is different") + + object ParameterNames : Incompatible("parameter names are different") + object TypeParameterNames : Incompatible("names of type parameters are different") + + object ValueParameterHasDefault : Incompatible("some parameters have default values") + object ValueParameterModifiers : Incompatible("parameter modifiers are different (vararg, coroutine, crossinline, noinline)") + + // Functions + + object FunctionModifiers : Incompatible("modifiers are different (external, infix, inline, operator, suspend, tailrec)") + + // Properties + + object PropertyKind : Incompatible("property kinds are different (val vs var)") + object PropertyModifiers : Incompatible("modifiers are different (const, lateinit)") + + // Classifiers + + object ClassKind : Incompatible("class kinds are different (class, interface, object, enum, annotation)") + + object ClassModifiers : Incompatible("modifiers are different (data)") + + object Supertypes : Incompatible("some supertypes are missing in the implementation") + + // Common + + object Modality : Incompatible("modality is different") + object Visibility : Incompatible("visibility is different") + + object TypeParameterUpperBounds : Incompatible("upper bounds of type parameters are different") + object TypeParameterVariance : Incompatible("declaration-site variances of type parameters are different") + object TypeParameterReified : Incompatible("some type parameter is reified in one declaration and non-reified in the other") + + object Unknown : Incompatible(null) + } + + object Compatible : Compatibility() + } + + // a is the declaration in common code, b is the definition in the platform-specific code + private fun areCompatibleCallables(a: CallableMemberDescriptor, b: CallableMemberDescriptor): Compatibility { + assert(a.name == b.name) { "This function should be invoked only for declarations with the same name: $a, $b" } + assert(a.containingDeclaration is ClassDescriptor == b.containingDeclaration is ClassDescriptor) { + "This function should be invoked only for declarations in the same kind of container (both members or both top level): $a, $b" + } + + val aExtensionReceiver = a.extensionReceiverParameter + val bExtensionReceiver = b.extensionReceiverParameter + if ((aExtensionReceiver != null) != (bExtensionReceiver != null)) return Incompatible.ParameterShape + + val aParams = a.valueParameters + val bParams = b.valueParameters + if (aParams.size != bParams.size) return Incompatible.ParameterCount + + val aTypeParams = a.typeParameters + val bTypeParams = b.typeParameters + if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount + + val substitutor = Substitutor(aTypeParams, bTypeParams) + + if (aParams.map { substitutor(it.type) } != bParams.map { it.type } || + aExtensionReceiver?.type?.let(substitutor) != bExtensionReceiver?.type) return Incompatible.ParameterTypes + if (substitutor(a.returnType) != b.returnType) return Incompatible.ReturnType + + if (!equalsBy(aParams, bParams, ValueParameterDescriptor::getName)) return Incompatible.ParameterNames + if (!equalsBy(aTypeParams, bTypeParams, TypeParameterDescriptor::getName)) return Incompatible.TypeParameterNames + + if (a.modality != b.modality) return Incompatible.Modality + if (a.visibility != b.visibility) return Incompatible.Visibility + + areCompatibleTypeParameters(aTypeParams, bTypeParams, substitutor).let { if (it != Compatible) return it } + + if (!equalsBy(aParams, bParams, ValueParameterDescriptor::declaresDefaultValue)) return Incompatible.ValueParameterHasDefault + if (!equalsBy(aParams, bParams, { p -> listOf(p.varargElementType != null, p.isCoroutine, p.isCrossinline, p.isNoinline) })) return Incompatible.ValueParameterModifiers + + when { + a is FunctionDescriptor && b is FunctionDescriptor -> areCompatibleFunctions(a, b).let { if (it != Compatible) return it } + a is PropertyDescriptor && b is PropertyDescriptor -> areCompatibleProperties(a, b).let { if (it != Compatible) return it } + else -> throw AssertionError("Unsupported declarations: $a, $b") + } + + // TODO: check 'impl' modifier + + return Compatible + } + + private fun areCompatibleTypeParameters(a: List, b: List, substitutor: Substitutor): Compatibility { + if (a.map { substitutor(it.defaultType) } != b.map { it.defaultType }) return Incompatible.TypeParameterUpperBounds + if (!equalsBy(a, b, TypeParameterDescriptor::getVariance)) return Incompatible.TypeParameterVariance + if (!equalsBy(a, b, TypeParameterDescriptor::isReified)) return Incompatible.TypeParameterReified + + return Compatible + } + + private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): Compatibility { + if (!equalBy(a, b) { f -> + listOf(f.isExternal, f.isInfix, f.isInline, f.isOperator, f.isSuspend, f.isTailrec) + }) return Incompatible.FunctionModifiers + + return Compatible + } + + private fun areCompatibleProperties(a: PropertyDescriptor, b: PropertyDescriptor): Compatibility { + if (!equalBy(a, b) { p -> p.isVar }) return Incompatible.PropertyKind + if (!equalBy(a, b) { p -> listOf(p.isConst, p.isLateInit) }) return Incompatible.PropertyModifiers + + return Compatible + } + + private fun areCompatibleClassifiers(a: ClassDescriptor, other: ClassifierDescriptor): Compatibility { + assert(a.fqNameUnsafe == other.fqNameUnsafe) { "This function should be invoked only for declarations with the same name: $a, $other" } + + val b = when (other) { + is ClassDescriptor -> other + is TypeAliasDescriptor -> other.classDescriptor ?: return Incompatible.Unknown + else -> throw AssertionError("Incorrect impl classifier for $a: $other") + } + + if (a.kind != b.kind) return Incompatible.ClassKind + + val aTypeParams = a.declaredTypeParameters + val bTypeParams = b.declaredTypeParameters + if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount + + val substitutor = Substitutor(aTypeParams, bTypeParams) + + if (a.modality != b.modality) return Incompatible.Modality + if (a.visibility != b.visibility) return Incompatible.Visibility + + areCompatibleTypeParameters(aTypeParams, bTypeParams, substitutor).let { if (it != Compatible) return it } + + if (!equalBy(a, b) { it.isData }) return Incompatible.ClassModifiers + + if (!b.typeConstructor.supertypes.containsAll(a.typeConstructor.supertypes.map(substitutor))) return Incompatible.Supertypes + + // TODO: check scopes + // TODO: check 'impl' modifier + + return Compatible + } + + private inline fun equalBy(first: T, second: T, selector: (T) -> K): Boolean = + selector(first) == selector(second) + + private inline fun equalsBy(first: List, second: List, selector: (T) -> K): Boolean { + for (i in first.indices) { + if (selector(first[i]) != selector(second[i])) return false + } + + return true + } + + // This substitutor takes the type from A's signature and returns the type that should be in that place in B's signature + private class Substitutor( + aTypeParams: List, + bTypeParams: List + ) : (KotlinType?) -> KotlinType? { + val typeSubstitutor = TypeSubstitutor.create(TypeConstructorSubstitution.createByParametersMap( + aTypeParams.keysToMap { bTypeParams[it.index].defaultType.asTypeProjection() } + )) + + override fun invoke(type: KotlinType?): KotlinType? = + type?.asTypeProjection()?.let(typeSubstitutor::substitute)?.type + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.kt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.kt index 1c72d1d2773..6454c30f5b4 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.kt @@ -1,3 +1,4 @@ +// !DIAGNOSTICS: -PLATFORM_DEFINITION_WITHOUT_DECLARATION // !LANGUAGE: +MultiPlatformProjects // MODULE: m1-common // FILE: common.kt diff --git a/compiler/testData/multiplatform/genericDeclarations/common.kt b/compiler/testData/multiplatform/genericDeclarations/common.kt new file mode 100644 index 00000000000..9cff5eb1326 --- /dev/null +++ b/compiler/testData/multiplatform/genericDeclarations/common.kt @@ -0,0 +1,13 @@ +platform fun f1(): T + +platform fun f2(t: T) + +platform fun , V : MutableList> f3(v: Map>, w: Comparable<*>) + +platform fun > Array.sort(): Unit + +platform class C1 +platform class C2> +platform class C3> + +platform abstract class AbstractList : MutableList diff --git a/compiler/testData/multiplatform/genericDeclarations/jvm.kt b/compiler/testData/multiplatform/genericDeclarations/jvm.kt new file mode 100644 index 00000000000..a0af9e5b67e --- /dev/null +++ b/compiler/testData/multiplatform/genericDeclarations/jvm.kt @@ -0,0 +1,15 @@ +impl fun f1(): T = throw AssertionError() + +impl fun f2(t: T) {} + +impl fun , V : MutableList> f3(v: Map>, w: Comparable<*>) {} + +impl fun > Array.sort(): Unit { + java.util.Arrays.sort(this) +} + +impl class C1 +impl class C2> +impl class C3> + +impl abstract class AbstractList : MutableList, java.io.Serializable diff --git a/compiler/testData/multiplatform/genericDeclarations/output.txt b/compiler/testData/multiplatform/genericDeclarations/output.txt new file mode 100644 index 00000000000..ce9e219309f --- /dev/null +++ b/compiler/testData/multiplatform/genericDeclarations/output.txt @@ -0,0 +1,8 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: OK +Output: + diff --git a/compiler/testData/multiplatform/implementClassWithTypeAlias/common.kt b/compiler/testData/multiplatform/implementClassWithTypeAlias/common.kt new file mode 100644 index 00000000000..fc53898517d --- /dev/null +++ b/compiler/testData/multiplatform/implementClassWithTypeAlias/common.kt @@ -0,0 +1,3 @@ +platform class C1 { + fun foo(a: A): List? +} diff --git a/compiler/testData/multiplatform/implementClassWithTypeAlias/jvm.kt b/compiler/testData/multiplatform/implementClassWithTypeAlias/jvm.kt new file mode 100644 index 00000000000..916937db06e --- /dev/null +++ b/compiler/testData/multiplatform/implementClassWithTypeAlias/jvm.kt @@ -0,0 +1,4 @@ +impl typealias C1 = C1Impl +class C1Impl { + fun foo(a: A): List? = null +} diff --git a/compiler/testData/multiplatform/implementClassWithTypeAlias/output.txt b/compiler/testData/multiplatform/implementClassWithTypeAlias/output.txt new file mode 100644 index 00000000000..f12f8c5d70d --- /dev/null +++ b/compiler/testData/multiplatform/implementClassWithTypeAlias/output.txt @@ -0,0 +1,11 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: OK +Output: +compiler/testData/multiplatform/implementClassWithTypeAlias/jvm.kt:3:13: warning: parameter 'a' is never used + fun foo(a: A): List? = null + ^ + diff --git a/compiler/testData/multiplatform/incompatibleCallables/common.kt b/compiler/testData/multiplatform/incompatibleCallables/common.kt new file mode 100644 index 00000000000..442585e840a --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleCallables/common.kt @@ -0,0 +1,36 @@ +platform fun f1() + +platform fun f2(name: String) + +platform fun f3(name: String) +platform fun String.f3ext() + +platform fun f4(name: String) + +platform fun String.f5() + +platform fun f6(p1: String, p2: Int) + +platform fun f7() + +internal platform fun f8() +private platform fun f9() +public platform fun f10() + +platform fun f11() +platform fun > f12() +platform fun > f13() + +platform inline fun f14() +platform inline fun f15() + +platform fun f16(s: String) + +platform fun f17(vararg s: String) +platform fun f18(s: Array) +platform inline fun f19(crossinline s: () -> Unit) +platform inline fun f20(s: () -> Unit) +platform inline fun f21(noinline s: () -> Unit) +platform inline fun f22(s: () -> Unit) +platform fun f23(coroutine c: Unit.() -> Continuation) +platform fun f24(c: Unit.() -> Continuation) diff --git a/compiler/testData/multiplatform/incompatibleCallables/jvm.kt b/compiler/testData/multiplatform/incompatibleCallables/jvm.kt new file mode 100644 index 00000000000..f435a456294 --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleCallables/jvm.kt @@ -0,0 +1,36 @@ +impl fun f1(): String = "" + +impl fun f2(otherName: String) {} + +impl fun f3(name: Double) {} +impl fun Double.f3ext() {} + +impl fun String.f4() {} + +impl fun f5(name: String) {} + +impl fun f6(p2: Int) {} + +impl fun f7() {} + +public impl fun f8() {} +internal impl fun f9() {} +private impl fun f10() {} + +impl fun f11() {} +impl fun > f12() {} +impl fun > f13() {} + +impl inline fun f14() {} +impl inline fun f15() {} + +impl fun f16(s: String = "") {} + +impl fun f17(s: Array) {} +impl fun f18(vararg s: String) {} +impl inline fun f19(s: () -> Unit) {} +impl inline fun f20(crossinline s: () -> Unit) {} +impl inline fun f21(s: () -> Unit) {} +impl inline fun f22(noinline s: () -> Unit) {} +impl fun f23(c: Unit.() -> Continuation) {} +impl fun f24(coroutine c: Unit.() -> Continuation) {} diff --git a/compiler/testData/multiplatform/incompatibleCallables/output.txt b/compiler/testData/multiplatform/incompatibleCallables/output.txt new file mode 100644 index 00000000000..d335a28cd2b --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleCallables/output.txt @@ -0,0 +1,206 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: COMPILATION_ERROR +Output: +compiler/testData/multiplatform/incompatibleCallables/common.kt:1:1: error: no definition is found for platform declaration 'f1' +The following declaration is incompatible because return type is different: + public impl fun f1(): String + +platform fun f1() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:3:1: error: no definition is found for platform declaration 'f2' +The following declaration is incompatible because parameter names are different: + public impl fun f2(otherName: String): Unit + +platform fun f2(name: String) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:5:1: error: no definition is found for platform declaration 'f3' +The following declaration is incompatible because parameter types are different: + public impl fun f3(name: Double): Unit + +platform fun f3(name: String) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:6:1: error: no definition is found for platform declaration 'f3ext' +The following declaration is incompatible because parameter types are different: + public impl fun Double.f3ext(): Unit + +platform fun String.f3ext() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:8:1: error: no definition is found for platform declaration 'f4' +The following declaration is incompatible because parameter shapes are different (extension vs non-extension): + public impl fun String.f4(): Unit + +platform fun f4(name: String) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:10:1: error: no definition is found for platform declaration 'f5' +The following declaration is incompatible because parameter shapes are different (extension vs non-extension): + public impl fun f5(name: String): Unit + +platform fun String.f5() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:12:1: error: no definition is found for platform declaration 'f6' +The following declaration is incompatible because number of value parameters is different: + public impl fun f6(p2: Int): Unit + +platform fun f6(p1: String, p2: Int) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:14:1: error: no definition is found for platform declaration 'f7' +The following declaration is incompatible because number of type parameters is different: + public impl fun f7(): Unit + +platform fun f7() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:16:1: error: no definition is found for platform declaration 'f8' +The following declaration is incompatible because visibility is different: + public impl fun f8(): Unit + +internal platform fun f8() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:17:1: error: no definition is found for platform declaration 'f9' +The following declaration is incompatible because visibility is different: + internal impl fun f9(): Unit + +private platform fun f9() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:18:1: error: no definition is found for platform declaration 'f10' +The following declaration is incompatible because visibility is different: + private impl fun f10(): Unit + +public platform fun f10() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:24:1: error: no definition is found for platform declaration 'f14' +The following declaration is incompatible because some type parameter is reified in one declaration and non-reified in the other: + public inline impl fun f14(): Unit + +platform inline fun f14() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:25:1: error: no definition is found for platform declaration 'f15' +The following declaration is incompatible because some type parameter is reified in one declaration and non-reified in the other: + public inline impl fun f15(): Unit + +platform inline fun f15() +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:27:1: error: no definition is found for platform declaration 'f16' +The following declaration is incompatible because some parameters have default values: + public impl fun f16(s: String = ...): Unit + +platform fun f16(s: String) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:29:1: error: no definition is found for platform declaration 'f17' +The following declaration is incompatible because parameter modifiers are different (vararg, coroutine, crossinline, noinline): + public impl fun f17(s: Array): Unit + +platform fun f17(vararg s: String) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:30:1: error: no definition is found for platform declaration 'f18' +The following declaration is incompatible because parameter modifiers are different (vararg, coroutine, crossinline, noinline): + public impl fun f18(vararg s: String): Unit + +platform fun f18(s: Array) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:31:1: error: no definition is found for platform declaration 'f19' +The following declaration is incompatible because parameter modifiers are different (vararg, coroutine, crossinline, noinline): + public inline impl fun f19(s: () -> Unit): Unit + +platform inline fun f19(crossinline s: () -> Unit) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:32:1: error: no definition is found for platform declaration 'f20' +The following declaration is incompatible because parameter modifiers are different (vararg, coroutine, crossinline, noinline): + public inline impl fun f20(crossinline s: () -> Unit): Unit + +platform inline fun f20(s: () -> Unit) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:33:1: error: no definition is found for platform declaration 'f21' +The following declaration is incompatible because parameter modifiers are different (vararg, coroutine, crossinline, noinline): + public inline impl fun f21(s: () -> Unit): Unit + +platform inline fun f21(noinline s: () -> Unit) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:34:1: error: no definition is found for platform declaration 'f22' +The following declaration is incompatible because parameter modifiers are different (vararg, coroutine, crossinline, noinline): + public inline impl fun f22(noinline s: () -> Unit): Unit + +platform inline fun f22(s: () -> Unit) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:35:1: error: no definition is found for platform declaration 'f23' +The following declaration is incompatible because parameter modifiers are different (vararg, coroutine, crossinline, noinline): + public impl fun f23(c: Unit.() -> Continuation): Unit + +platform fun f23(coroutine c: Unit.() -> Continuation) +^ +compiler/testData/multiplatform/incompatibleCallables/common.kt:36:1: error: no definition is found for platform declaration 'f24' +The following declaration is incompatible because parameter modifiers are different (vararg, coroutine, crossinline, noinline): + public impl fun f24(coroutine c: Unit.() -> Continuation): Unit + +platform fun f24(c: Unit.() -> Continuation) +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:1:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f1(): String = "" +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:3:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f2(otherName: String) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:5:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f3(name: Double) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:6:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun Double.f3ext() {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:8:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun String.f4() {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:10:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f5(name: String) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:12:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f6(p2: Int) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:14:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f7() {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:16:8: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +public impl fun f8() {} + ^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:17:10: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +internal impl fun f9() {} + ^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:18:9: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +private impl fun f10() {} + ^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:24:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl inline fun f14() {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:25:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl inline fun f15() {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:27:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f16(s: String = "") {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:29:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f17(s: Array) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:30:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f18(vararg s: String) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:31:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl inline fun f19(s: () -> Unit) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:32:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl inline fun f20(crossinline s: () -> Unit) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:33:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl inline fun f21(s: () -> Unit) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:34:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl inline fun f22(noinline s: () -> Unit) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:35:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f23(c: Unit.() -> Continuation) {} +^ +compiler/testData/multiplatform/incompatibleCallables/jvm.kt:36:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f24(coroutine c: Unit.() -> Continuation) {} +^ + diff --git a/compiler/testData/multiplatform/incompatibleClasses/common.kt b/compiler/testData/multiplatform/incompatibleClasses/common.kt new file mode 100644 index 00000000000..8bf528b935c --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleClasses/common.kt @@ -0,0 +1,25 @@ +platform class PClass +platform interface PInterface +platform object PObject +platform enum class PEnumClass +platform annotation class PAnnotationClass + +internal platform object InternalObject +public platform object PublicObject +private platform object PrivateObject + +open platform class OpenClass +abstract platform class AbstractClass +final platform class FinalClass + +// platform data class DataClass(val x: Int) +platform class NonDataClass(x: Int) + +platform class C1 +platform class C2 +platform class C3 + +platform class C4 + + +platform abstract class ExtendsNumber : Number diff --git a/compiler/testData/multiplatform/incompatibleClasses/jvm.kt b/compiler/testData/multiplatform/incompatibleClasses/jvm.kt new file mode 100644 index 00000000000..ca3f37c68ea --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleClasses/jvm.kt @@ -0,0 +1,25 @@ +impl interface PClass +impl object PInterface +impl enum class PObject +impl annotation class PEnumClass +impl class PAnnotationClass + +private impl object InternalObject +internal impl object PublicObject +public impl object PrivateObject + +final impl class OpenClass +open impl class AbstractClass +abstract impl class FinalClass + +// impl class DataClass(val x: Int) +impl data class NonDataClass(val x: Int) + +impl class C1 +impl class C2 +impl class C3 + +impl typealias C4 = C4Impl +class C4Impl + +impl abstract class ExtendsNumber : Any() diff --git a/compiler/testData/multiplatform/incompatibleClasses/output.txt b/compiler/testData/multiplatform/incompatibleClasses/output.txt new file mode 100644 index 00000000000..75ae5d7486c --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleClasses/output.txt @@ -0,0 +1,143 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: COMPILATION_ERROR +Output: +compiler/testData/multiplatform/incompatibleClasses/common.kt:1:16: error: no definition is found for platform declaration 'PClass' +The following declaration is incompatible because class kinds are different (class, interface, object, enum, annotation): + public impl interface PClass + +platform class PClass + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:2:20: error: no definition is found for platform declaration 'PInterface' +The following declaration is incompatible because class kinds are different (class, interface, object, enum, annotation): + public impl object PInterface + +platform interface PInterface + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:3:10: error: no definition is found for platform declaration 'PObject' +The following declaration is incompatible because class kinds are different (class, interface, object, enum, annotation): + public final impl enum class PObject : Enum + +platform object PObject + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:4:21: error: no definition is found for platform declaration 'PEnumClass' +The following declaration is incompatible because class kinds are different (class, interface, object, enum, annotation): + public final impl annotation class PEnumClass : Annotation + +platform enum class PEnumClass + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:5:27: error: no definition is found for platform declaration 'PAnnotationClass' +The following declaration is incompatible because class kinds are different (class, interface, object, enum, annotation): + public final impl class PAnnotationClass + +platform annotation class PAnnotationClass + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:7:19: error: no definition is found for platform declaration 'InternalObject' +The following declaration is incompatible because visibility is different: + private impl object InternalObject + +internal platform object InternalObject + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:8:17: error: no definition is found for platform declaration 'PublicObject' +The following declaration is incompatible because visibility is different: + internal impl object PublicObject + +public platform object PublicObject + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:9:18: error: no definition is found for platform declaration 'PrivateObject' +The following declaration is incompatible because visibility is different: + public impl object PrivateObject + +private platform object PrivateObject + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:11:21: error: no definition is found for platform declaration 'OpenClass' +The following declaration is incompatible because modality is different: + public final impl class OpenClass + +open platform class OpenClass + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:12:25: error: no definition is found for platform declaration 'AbstractClass' +The following declaration is incompatible because modality is different: + public open impl class AbstractClass + +abstract platform class AbstractClass + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:13:22: error: no definition is found for platform declaration 'FinalClass' +The following declaration is incompatible because modality is different: + public abstract impl class FinalClass + +final platform class FinalClass + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:16:16: error: no definition is found for platform declaration 'NonDataClass' +The following declaration is incompatible because modifiers are different (data): + public final impl data class NonDataClass + +platform class NonDataClass(x: Int) + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:18:16: error: no definition is found for platform declaration 'C1' +The following declaration is incompatible because number of type parameters is different: + public final impl class C1 + +platform class C1 + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:19:16: error: no definition is found for platform declaration 'C2' +The following declaration is incompatible because declaration-site variances of type parameters are different: + public final impl class C2 + +platform class C2 + ^ +compiler/testData/multiplatform/incompatibleClasses/common.kt:25:25: error: no definition is found for platform declaration 'ExtendsNumber' +The following declaration is incompatible because some supertypes are missing in the implementation: + public abstract impl class ExtendsNumber + +platform abstract class ExtendsNumber : Number + ^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:1:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl interface PClass +^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:2:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl object PInterface +^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:3:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl enum class PObject +^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:4:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl annotation class PEnumClass +^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:5:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl class PAnnotationClass +^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:7:9: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +private impl object InternalObject + ^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:8:10: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +internal impl object PublicObject + ^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:9:8: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +public impl object PrivateObject + ^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:11:7: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +final impl class OpenClass + ^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:12:6: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +open impl class AbstractClass + ^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:13:10: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +abstract impl class FinalClass + ^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:16:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl data class NonDataClass(val x: Int) +^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:18:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl class C1 +^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:19:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl class C2 +^ +compiler/testData/multiplatform/incompatibleClasses/jvm.kt:25:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl abstract class ExtendsNumber : Any() +^ + diff --git a/compiler/testData/multiplatform/incompatibleFunctions/common.kt b/compiler/testData/multiplatform/incompatibleFunctions/common.kt new file mode 100644 index 00000000000..22f5fa1c0ae --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleFunctions/common.kt @@ -0,0 +1,14 @@ +platform infix fun Int.plus(s: CharSequence): Int +platform fun Int.minus(s: String): Int + +platform operator fun Double.times(x: CharArray) +platform fun Double.divide(x: ByteArray) + +platform external fun f1() +platform fun g1() + +platform inline fun f2() +platform fun g2() + +platform tailrec fun f3() +platform fun g3() diff --git a/compiler/testData/multiplatform/incompatibleFunctions/jvm.kt b/compiler/testData/multiplatform/incompatibleFunctions/jvm.kt new file mode 100644 index 00000000000..64d18ddacef --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleFunctions/jvm.kt @@ -0,0 +1,14 @@ +impl fun Int.plus(s: CharSequence): Int = 0 +impl infix fun Int.minus(s: String): Int = 1 + +impl fun Double.times(x: CharArray) {} +impl operator fun Double.divide(x: ByteArray) {} + +impl fun f1() {} +impl external fun g1() + +impl fun f2() {} +impl inline fun g2() {} + +impl fun f3() {} +impl tailrec fun g3() {} diff --git a/compiler/testData/multiplatform/incompatibleFunctions/output.txt b/compiler/testData/multiplatform/incompatibleFunctions/output.txt new file mode 100644 index 00000000000..c770dc78f0b --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleFunctions/output.txt @@ -0,0 +1,101 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: COMPILATION_ERROR +Output: +compiler/testData/multiplatform/incompatibleFunctions/common.kt:1:1: error: no definition is found for platform declaration 'plus' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public impl fun Int.plus(s: CharSequence): Int + +platform infix fun Int.plus(s: CharSequence): Int +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:2:1: error: no definition is found for platform declaration 'minus' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public infix impl fun Int.minus(s: String): Int + +platform fun Int.minus(s: String): Int +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:4:1: error: no definition is found for platform declaration 'times' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public impl fun Double.times(x: CharArray): Unit + +platform operator fun Double.times(x: CharArray) +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:5:1: error: no definition is found for platform declaration 'divide' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public operator impl fun Double.divide(x: ByteArray): Unit + +platform fun Double.divide(x: ByteArray) +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:7:1: error: no definition is found for platform declaration 'f1' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public impl fun f1(): Unit + +platform external fun f1() +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:8:1: error: no definition is found for platform declaration 'g1' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public external impl fun g1(): Unit + +platform fun g1() +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:10:1: error: no definition is found for platform declaration 'f2' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public impl fun f2(): Unit + +platform inline fun f2() +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:11:1: error: no definition is found for platform declaration 'g2' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public inline impl fun g2(): Unit + +platform fun g2() +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:13:1: error: no definition is found for platform declaration 'f3' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public impl fun f3(): Unit + +platform tailrec fun f3() +^ +compiler/testData/multiplatform/incompatibleFunctions/common.kt:14:1: error: no definition is found for platform declaration 'g3' +The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): + public tailrec impl fun g3(): Unit + +platform fun g3() +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:1:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun Int.plus(s: CharSequence): Int = 0 +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:2:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl infix fun Int.minus(s: String): Int = 1 +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:4:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun Double.times(x: CharArray) {} +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:5:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl operator fun Double.divide(x: ByteArray) {} +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:5:6: error: 'operator' modifier is inapplicable on this function: illegal function name +impl operator fun Double.divide(x: ByteArray) {} + ^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:7:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f1() {} +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:8:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl external fun g1() +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:10:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f2() {} +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:11:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl inline fun g2() {} +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:13:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl fun f3() {} +^ +compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:14:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl tailrec fun g3() {} +^ + diff --git a/compiler/testData/multiplatform/incompatibleProperties/common.kt b/compiler/testData/multiplatform/incompatibleProperties/common.kt new file mode 100644 index 00000000000..8f4eade6f63 --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleProperties/common.kt @@ -0,0 +1,2 @@ +platform val pval: String +platform var pvar: String diff --git a/compiler/testData/multiplatform/incompatibleProperties/jvm.kt b/compiler/testData/multiplatform/incompatibleProperties/jvm.kt new file mode 100644 index 00000000000..34770ea3eb5 --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleProperties/jvm.kt @@ -0,0 +1,2 @@ +impl var pval: String = "" +impl val pvar: String = "" diff --git a/compiler/testData/multiplatform/incompatibleProperties/output.txt b/compiler/testData/multiplatform/incompatibleProperties/output.txt new file mode 100644 index 00000000000..97a2ae8a542 --- /dev/null +++ b/compiler/testData/multiplatform/incompatibleProperties/output.txt @@ -0,0 +1,26 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: COMPILATION_ERROR +Output: +compiler/testData/multiplatform/incompatibleProperties/common.kt:1:1: error: no definition is found for platform declaration 'pval' +The following declaration is incompatible because property kinds are different (val vs var): + public var pval: String + +platform val pval: String +^ +compiler/testData/multiplatform/incompatibleProperties/common.kt:2:1: error: no definition is found for platform declaration 'pvar' +The following declaration is incompatible because property kinds are different (val vs var): + public val pvar: String + +platform var pvar: String +^ +compiler/testData/multiplatform/incompatibleProperties/jvm.kt:1:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl var pval: String = "" +^ +compiler/testData/multiplatform/incompatibleProperties/jvm.kt:2:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl val pvar: String = "" +^ + diff --git a/compiler/tests-common/org/jetbrains/kotlin/tests/di/injection.kt b/compiler/tests-common/org/jetbrains/kotlin/tests/di/injection.kt index 7f6f01e17cc..798be26e1d4 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/tests/di/injection.kt +++ b/compiler/tests-common/org/jetbrains/kotlin/tests/di/injection.kt @@ -18,8 +18,6 @@ package org.jetbrains.kotlin.tests.di import com.intellij.openapi.project.Project import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl -import org.jetbrains.kotlin.container.* -import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.getValue import org.jetbrains.kotlin.container.useImpl diff --git a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTest.kt b/compiler/tests/org/jetbrains/kotlin/multiplatform/AbstractMultiPlatformIntegrationTest.kt similarity index 61% rename from compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTest.kt rename to compiler/tests/org/jetbrains/kotlin/multiplatform/AbstractMultiPlatformIntegrationTest.kt index 3c8e7dcb5a7..461ce95370a 100644 --- a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/multiplatform/AbstractMultiPlatformIntegrationTest.kt @@ -24,9 +24,9 @@ import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import java.io.File -class MultiPlatformIntegrationTest : KtUsefulTestCase() { +abstract class AbstractMultiPlatformIntegrationTest : KtUsefulTestCase() { fun doTest(directoryPath: String) { - val root = File(KotlinTestUtils.getTestDataPathBase() + directoryPath) + val root = File(directoryPath).apply { assert(exists()) } val commonSrc = File(root, "common.kt") val jsSrc = File(root, "js.kt") val jvmSrc = File(root, "jvm.kt") @@ -46,31 +46,31 @@ class MultiPlatformIntegrationTest : KtUsefulTestCase() { appendln("Output:") appendln(commonOutput) - val (jvmOutput, jvmExitCode) = AbstractCliTest.executeCompilerGrabOutput(K2JVMCompiler(), listOf( - jvmSrc.absolutePath, commonSrc.absolutePath, - "-d", jvmDest.absolutePath, - "-Xmulti-platform" - )) - appendln("-- JVM --") - appendln("Exit code: $jvmExitCode") - appendln("Output:") - appendln(jvmOutput) + if (jvmSrc.exists()) { + val (jvmOutput, jvmExitCode) = AbstractCliTest.executeCompilerGrabOutput(K2JVMCompiler(), listOf( + jvmSrc.absolutePath, commonSrc.absolutePath, + "-d", jvmDest.absolutePath, + "-Xmulti-platform" + )) + appendln("-- JVM --") + appendln("Exit code: $jvmExitCode") + appendln("Output:") + appendln(jvmOutput) + } - val (jsOutput, jsExitCode) = AbstractCliTest.executeCompilerGrabOutput(K2JSCompiler(), listOf( - jsSrc.absolutePath, commonSrc.absolutePath, - "-output", jsDest.absolutePath, - "-Xmulti-platform" - )) - appendln("-- JS --") - appendln("Exit code: $jsExitCode") - appendln("Output:") - append(jsOutput) + if (jsSrc.exists()) { + val (jsOutput, jsExitCode) = AbstractCliTest.executeCompilerGrabOutput(K2JSCompiler(), listOf( + jsSrc.absolutePath, commonSrc.absolutePath, + "-output", jsDest.absolutePath, + "-Xmulti-platform" + )) + appendln("-- JS --") + appendln("Exit code: $jsExitCode") + appendln("Output:") + append(jsOutput) + } } KotlinTestUtils.assertEqualsToFile(File(root, "output.txt"), result) } - - fun testSimple() { - doTest("/multiplatform/simple/") - } } diff --git a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java new file mode 100644 index 00000000000..f259e884f8e --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java @@ -0,0 +1,121 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.multiplatform; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/multiplatform") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatformIntegrationTest { + public void testAllFilesPresentInMultiplatform() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/multiplatform"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true); + } + + @TestMetadata("genericDeclarations") + public void testGenericDeclarations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/genericDeclarations/"); + doTest(fileName); + } + + @TestMetadata("implementClassWithTypeAlias") + public void testImplementClassWithTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/implementClassWithTypeAlias/"); + doTest(fileName); + } + + @TestMetadata("incompatibleCallables") + public void testIncompatibleCallables() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/incompatibleCallables/"); + doTest(fileName); + } + + @TestMetadata("incompatibleClasses") + public void testIncompatibleClasses() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/incompatibleClasses/"); + doTest(fileName); + } + + @TestMetadata("incompatibleFunctions") + public void testIncompatibleFunctions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/incompatibleFunctions/"); + doTest(fileName); + } + + @TestMetadata("incompatibleProperties") + public void testIncompatibleProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/incompatibleProperties/"); + doTest(fileName); + } + + @TestMetadata("simple") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/simple/"); + doTest(fileName); + } + + @TestMetadata("compiler/testData/multiplatform/classScopes") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ClassScopes extends AbstractMultiPlatformIntegrationTest { + public void testAllFilesPresentInClassScopes() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/multiplatform/classScopes"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true); + } + + @TestMetadata("constructorIncorrectSignature") + public void testConstructorIncorrectSignature() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/classScopes/constructorIncorrectSignature/"); + doTest(fileName); + } + + @TestMetadata("functionIncorrectSignature") + public void testFunctionIncorrectSignature() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/classScopes/functionIncorrectSignature/"); + doTest(fileName); + } + + @TestMetadata("missingConstructor") + public void testMissingConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/classScopes/missingConstructor/"); + doTest(fileName); + } + + @TestMetadata("missingFunction") + public void testMissingFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/classScopes/missingFunction/"); + doTest(fileName); + } + + @TestMetadata("simple") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/classScopes/simple/"); + doTest(fileName); + } + + } + +} diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 404e225990d..244e5bf038c 100755 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.android.* import org.jetbrains.kotlin.android.configure.AbstractConfigureProjectTest import org.jetbrains.kotlin.android.intentions.AbstractAndroidIntentionTest import org.jetbrains.kotlin.android.intentions.AbstractAndroidResourceIntentionTest +import org.jetbrains.kotlin.android.lint.AbstractKotlinLintTest import org.jetbrains.kotlin.android.quickfixes.AbstractAndroidQuickFixMultiFileTest import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessorBoxTest import org.jetbrains.kotlin.annotation.processing.test.sourceRetention.AbstractBytecodeListingTestForSourceRetention @@ -131,6 +132,7 @@ import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.jps.build.* import org.jetbrains.kotlin.jps.build.android.AbstractAndroidJpsTestCase import org.jetbrains.kotlin.jps.incremental.AbstractProtoComparisonTest +import org.jetbrains.kotlin.js.test.semantics.* import org.jetbrains.kotlin.jvm.compiler.* import org.jetbrains.kotlin.jvm.runtime.AbstractJvm8RuntimeDescriptorLoaderTest import org.jetbrains.kotlin.jvm.runtime.AbstractJvmRuntimeDescriptorLoaderTest @@ -139,6 +141,7 @@ import org.jetbrains.kotlin.lang.resolve.android.test.AbstractAndroidBoxTest import org.jetbrains.kotlin.lang.resolve.android.test.AbstractAndroidBytecodeShapeTest import org.jetbrains.kotlin.lang.resolve.android.test.AbstractAndroidSyntheticPropertyDescriptorTest import org.jetbrains.kotlin.modules.xml.AbstractModuleXmlParserTest +import org.jetbrains.kotlin.multiplatform.AbstractMultiPlatformIntegrationTest import org.jetbrains.kotlin.parsing.AbstractParsingTest import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest import org.jetbrains.kotlin.renderer.AbstractDescriptorRendererTest @@ -154,8 +157,6 @@ import org.jetbrains.kotlin.serialization.AbstractLocalClassProtoTest import org.jetbrains.kotlin.shortenRefs.AbstractShortenRefsTest import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.types.AbstractTypeBindingTest -import org.jetbrains.kotlin.android.lint.AbstractKotlinLintTest -import org.jetbrains.kotlin.js.test.semantics.* import java.io.File import java.lang.IllegalArgumentException import java.util.* @@ -187,11 +188,14 @@ fun main(args: Array) { model("diagnostics/testsWithJsStdLibAndBackendCompilation") } - testClass() { model("diagnostics/testWithModifiedMockJdk") } + testClass() { + model("multiplatform", extension = null, recursive = true, excludeParentDirs = true) + } + testClass() { model("foreignAnnotations/tests") } diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt index 0ba612c3a7f..0a7a109ae82 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt @@ -19,25 +19,23 @@ package org.jetbrains.kotlin.js.resolve import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.useImpl import org.jetbrains.kotlin.container.useInstance -import org.jetbrains.kotlin.js.resolve.diagnostics.JsCallChecker -import org.jetbrains.kotlin.js.resolve.diagnostics.JsNameChecker -import org.jetbrains.kotlin.js.resolve.diagnostics.JsNameClashChecker -import org.jetbrains.kotlin.js.resolve.diagnostics.JsNativeRttiChecker -import org.jetbrains.kotlin.js.resolve.diagnostics.JsReifiedNativeChecker -import org.jetbrains.kotlin.js.resolve.diagnostics.NativeInnerClassChecker +import org.jetbrains.kotlin.js.resolve.diagnostics.* import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap import org.jetbrains.kotlin.resolve.IdentifierChecker import org.jetbrains.kotlin.resolve.OverloadFilter import org.jetbrains.kotlin.resolve.PlatformConfigurator -import org.jetbrains.kotlin.js.resolve.diagnostics.JsReflectionAPICallChecker +import org.jetbrains.kotlin.resolve.checkers.PlatformImplDeclarationChecker import org.jetbrains.kotlin.resolve.scopes.SyntheticConstructorsProvider import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes import org.jetbrains.kotlin.types.DynamicTypesAllowed object JsPlatformConfigurator : PlatformConfigurator( DynamicTypesAllowed(), - additionalDeclarationCheckers = listOf(NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(), - NativeInnerClassChecker(), JsNameChecker), + additionalDeclarationCheckers = listOf( + NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(), NativeInnerClassChecker(), + JsNameChecker, + PlatformImplDeclarationChecker() + ), additionalCallCheckers = listOf(), additionalTypeCheckers = listOf(), additionalClassifierUsageCheckers = listOf(),