diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 182337a178b..41364d42c08 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -324,6 +324,7 @@ public interface Errors { DiagnosticFactory0 INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INLINE_CLASS_WITH_INITIALIZER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory1 INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE = DiagnosticFactory1.create(ERROR); // Secondary constructors 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 6119a71fbf8..4695b214dfd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -650,6 +650,7 @@ public class DefaultErrorMessages { MAP.put(INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER, "Inline class primary constructor must have only final read-only (val) property parameter"); MAP.put(INLINE_CLASS_WITH_INITIALIZER, "Inline class cannot have an initializer block"); MAP.put(PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS, "Inline class cannot have properties with backing fields"); + MAP.put(INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE, "Inline class cannot have value parameter of type ''{0}''", RENDER_TYPE); MAP.put(VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED, "Variance annotations are only allowed for type parameters of classes and interfaces"); MAP.put(BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED, "Bounds are not allowed on type alias parameters"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt index 1291ca7aff2..e802b714320 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/InlineClassDeclarationChecker.kt @@ -14,6 +14,11 @@ import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.isInlineClass +import org.jetbrains.kotlin.resolve.substitutedUnderlyingType +import org.jetbrains.kotlin.types.typeUtil.isNothing +import org.jetbrains.kotlin.types.typeUtil.isTypeParameter +import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.utils.addToStdlib.safeAs object InlineClassDeclarationChecker : DeclarationChecker { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { @@ -71,6 +76,17 @@ object InlineClassDeclarationChecker : DeclarationChecker { return } + + val baseParameterType = descriptor.safeAs()?.defaultType?.substitutedUnderlyingType() + if (baseParameterType != null && + (baseParameterType.isUnit() || baseParameterType.isNothing() || baseParameterType.isTypeParameter()) + ) { + val typeReference = baseParameter.typeReference + if (typeReference != null) { + trace.report(Errors.INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE.on(typeReference, baseParameterType)) + return + } + } } private fun isParameterAcceptableForInlineClass(parameter: KtParameter): Boolean { diff --git a/compiler/testData/diagnostics/tests/inlineClasses/inlineClassWithForbiddenUnderlyingType.kt b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassWithForbiddenUnderlyingType.kt new file mode 100644 index 00000000000..036413bf0d5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassWithForbiddenUnderlyingType.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +InlineClasses + +inline class Foo(val x: T) +inline class FooNullable(val x: T?) + +inline class Bar(val u: Unit) +inline class BarNullable(val u: Unit?) + +inline class Baz(val u: Nothing) +inline class BazNullable(val u: Nothing?) diff --git a/compiler/testData/diagnostics/tests/inlineClasses/inlineClassWithForbiddenUnderlyingType.txt b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassWithForbiddenUnderlyingType.txt new file mode 100644 index 00000000000..4ab20769e03 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassWithForbiddenUnderlyingType.txt @@ -0,0 +1,49 @@ +package + +public final inline class Bar { + public constructor Bar(/*0*/ u: kotlin.Unit) + public final val u: kotlin.Unit + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} + +public final inline class BarNullable { + public constructor BarNullable(/*0*/ u: kotlin.Unit?) + public final val u: kotlin.Unit? + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} + +public final inline class Baz { + public constructor Baz(/*0*/ u: kotlin.Nothing) + public final val u: kotlin.Nothing + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} + +public final inline class BazNullable { + public constructor BazNullable(/*0*/ u: kotlin.Nothing?) + public final val u: kotlin.Nothing? + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} + +public final inline class Foo { + public constructor Foo(/*0*/ x: T) + public final val x: T + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} + +public final inline class FooNullable { + public constructor FooNullable(/*0*/ x: T?) + public final val x: T? + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/writeSignature/inlineClasses/genericInlineClassWithDefaultTypeParameter.kt b/compiler/testData/writeSignature/inlineClasses/genericInlineClassWithDefaultTypeParameter.kt index 6a43795701a..8430b20a0ba 100644 --- a/compiler/testData/writeSignature/inlineClasses/genericInlineClassWithDefaultTypeParameter.kt +++ b/compiler/testData/writeSignature/inlineClasses/genericInlineClassWithDefaultTypeParameter.kt @@ -1,5 +1,6 @@ // !LANGUAGE: +InlineClasses +@Suppress("INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE") inline class Default(val x: T) class Inv diff --git a/compiler/testData/writeSignature/inlineClasses/genericInlineClassWithNotNullTypeParameter.kt b/compiler/testData/writeSignature/inlineClasses/genericInlineClassWithNotNullTypeParameter.kt index f3632c16adb..d6d10565804 100644 --- a/compiler/testData/writeSignature/inlineClasses/genericInlineClassWithNotNullTypeParameter.kt +++ b/compiler/testData/writeSignature/inlineClasses/genericInlineClassWithNotNullTypeParameter.kt @@ -1,6 +1,9 @@ // !LANGUAGE: +InlineClasses +@Suppress("INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE") inline class NonNull(val x: T) + +@Suppress("INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE") inline class NullableValue(val x: T?) object Test { diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0484606d77c..9590870c720 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10872,6 +10872,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassImplementsCollection.kt"); } + @TestMetadata("inlineClassWithForbiddenUnderlyingType.kt") + public void testInlineClassWithForbiddenUnderlyingType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassWithForbiddenUnderlyingType.kt"); + } + @TestMetadata("inlineClassesInsideAnnotations.kt") public void testInlineClassesInsideAnnotations() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index df63df64a4d..f763379b1bc 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10872,6 +10872,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassImplementsCollection.kt"); } + @TestMetadata("inlineClassWithForbiddenUnderlyingType.kt") + public void testInlineClassWithForbiddenUnderlyingType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassWithForbiddenUnderlyingType.kt"); + } + @TestMetadata("inlineClassesInsideAnnotations.kt") public void testInlineClassesInsideAnnotations() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt");