From a25ba5baf11ab8c4548967bca7a8454b07a97ef0 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 19 May 2016 14:53:56 +0300 Subject: [PATCH] KT-12156: for the purposes of inline-related diagnostics treat function declaration as final if it is a member of a final class --- .../resolve/inline/InlineAnalyzerExtension.kt | 7 +++- .../tests/inline/overrideWithInline.kt | 32 +++++++++++++++++-- .../tests/inline/overrideWithInline.txt | 22 +++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt index 598ce384e44..9125554daa4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt @@ -98,7 +98,7 @@ object InlineAnalyzerExtension : FunctionAnalyzerExtension.AnalyzerExtension { } } - if (functionDescriptor.modality == Modality.FINAL) { + if (functionDescriptor.isEffectivelyFinal()) { if (overridesAnything) { trace.report(Errors.OVERRIDE_BY_INLINE.on(function)) } @@ -108,6 +108,11 @@ object InlineAnalyzerExtension : FunctionAnalyzerExtension.AnalyzerExtension { trace.report(Errors.DECLARATION_CANT_BE_INLINED.on(function)) } + private fun FunctionDescriptor.isEffectivelyFinal(): Boolean = + modality == Modality.FINAL || + containingDeclaration.let { containingDeclaration -> + containingDeclaration is ClassDescriptor && containingDeclaration.modality == Modality.FINAL + } private fun checkHasInlinableAndNullability( functionDescriptor: FunctionDescriptor, diff --git a/compiler/testData/diagnostics/tests/inline/overrideWithInline.kt b/compiler/testData/diagnostics/tests/inline/overrideWithInline.kt index 727e9145c4a..5b519286a02 100644 --- a/compiler/testData/diagnostics/tests/inline/overrideWithInline.kt +++ b/compiler/testData/diagnostics/tests/inline/overrideWithInline.kt @@ -8,10 +8,36 @@ interface IBase { class CDerived : IBase { override inline final fun foo() {} - override inline fun bar() {} + override inline fun bar() {} override inline final fun <reified T> qux(x: T) {} class CNested : IBase { + override inline final fun foo() {} + override inline fun bar() {} + override inline final fun <reified T> qux(x: T) {} + } + + val anObject = object : IBase { + override inline final fun foo() {} + override inline fun bar() {} + override inline final fun <reified T> qux(x: T) {} + } + + fun aMethod() { + class CLocal : IBase { + override inline final fun foo() {} + override inline fun bar() {} + override inline final fun <reified T> qux(x: T) {} + } + } +} + +open class COpen : IBase { + override inline final fun foo() {} + override inline fun bar() {} + override inline final fun <reified T> qux(x: T) {} + + open class COpenNested : IBase { override inline final fun foo() {} override inline fun bar() {} override inline final fun <reified T> qux(x: T) {} @@ -19,12 +45,12 @@ class CDerived : IBase { val anObject = object : IBase { override inline final fun foo() {} - override inline fun bar() {} + override inline fun bar() {} override inline final fun <reified T> qux(x: T) {} } fun aMethod() { - class CLocal : IBase { + open class COpenLocal : IBase { override inline final fun foo() {} override inline fun bar() {} override inline final fun <reified T> qux(x: T) {} diff --git a/compiler/testData/diagnostics/tests/inline/overrideWithInline.txt b/compiler/testData/diagnostics/tests/inline/overrideWithInline.txt index 368f6e28dbd..6998a93fa78 100644 --- a/compiler/testData/diagnostics/tests/inline/overrideWithInline.txt +++ b/compiler/testData/diagnostics/tests/inline/overrideWithInline.txt @@ -22,6 +22,28 @@ public final class CDerived : IBase { } } +public open class COpen : IBase { + public constructor COpen() + public final val anObject: IBase + public final fun aMethod(): kotlin.Unit + public open inline override /*1*/ fun bar(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final inline override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final inline override /*1*/ fun qux(/*0*/ x: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public open class COpenNested : IBase { + public constructor COpenNested() + public open inline override /*1*/ fun bar(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final inline override /*1*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final inline override /*1*/ fun qux(/*0*/ x: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + public interface IBase { public abstract fun bar(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean